2

我正在尝试按行对二维数组进行排序vector<vector<int> > a(M,vector<int>(N)),相对于它的第 n 列,如下所示:

sort(a.begin(),a.end(),
  (bind(&vector<int>::operator[],_1,n) >
   bind(&vector<int>::operator[],_2,n)));

但是我的编译器告诉我

error: no matching function for call to ‘bind(<unresolved overloaded function type>, const boost::lambda::placeholder1_type&, int)’
error: no matching function for call to ‘bind(<unresolved overloaded function type>, const boost::lambda::placeholder2_type&, int)’

我应该如何解决通话?

PS.:尝试了之前访问 operator[] 的更简单的版本

  vector<int> a(10);
  (bind(&vector<int>::operator[],_1,_2))(a,2);

这是直接从卡尔森的书中改编的复制粘贴。得到

error: no matching function for call to ‘bind(<unresolved overloaded function type>, const boost::lambda::placeholder1_type&, const boost::lambda::placeholder2_type&)’

也为此...

4

4 回答 4

3

使用 Boost.Phoenix,您可以使用 @sellibitze 在评论中提到的内容:

#include <iostream>
#include <vector>

#include <boost/phoenix.hpp>

namespace phx=boost::phoenix;

int main()
{
    std::vector<std::vector<int>> matrix
    {
        {1, 2, 3, 4},
        {4, 3, 4, 1},
        {9, 1, 0, 2},
        {3, 1, 5, 1}
    };

    const auto N = 2;

    using phx::arg_names::_1;
    using phx::arg_names::_2;

    std::sort( matrix.begin(), matrix.end(), _1[N] > _2[N] );

    for(const auto& row: matrix)
    {
        for(const auto& elem: row)
            std::cout << elem << ' ';

        std::cout << std::endl;
    }

    return 0;
}
于 2013-04-28T08:59:12.753 回答
2

std::vectorconst和无const版本operator[],编译器无法推断应该使用哪个重载。你可以这样做:

template <class R, class T, class... Args>
auto const_mem_fn(R (T::* pm)(Args...) const)
    -> decltype(std::mem_fn(pm))
{
    return std::mem_fn(pm);
}

int main()
{
    std::vector<std::vector<int>> matrix
    {
        {1, 2, 3, 4},
        {4, 3, 4, 1},
        {9, 1, 0, 2},
        {3, 1, 5, 1}
    };

    const auto N = 2;

    std::sort
    (
        matrix.begin(), matrix.end(),
        boost::bind(const_mem_fn(&std::vector<int>::operator[]), _1, N) >
        boost::bind(const_mem_fn(&std::vector<int>::operator[]), _2, N)
    );

    for(const auto& row: matrix)
    {
        for(const auto& elem: row)
            std::cout << elem << ' ';

        std::cout << std::endl;
    }

    return 0;
}

或者,没有const_mem_fn

const int& (std::vector<int>::*op_sq_br)(std::size_t) const = &std::vector<int>::operator[];

std::sort
(
    matrix.begin(), matrix.end(),
    boost::bind(op_sq_br, _1, N) >
    boost::bind(op_sq_br, _2, N)
);

输出:

3 1 5 1
4 3 4 1
1 2 3 4
9 1 0 2

于 2013-04-28T07:50:26.773 回答
2

正如@soon 所说,&std::vector<int>::operator[]指的是重载集。但是您不能将这样的东西传递给函数模板并期望它推断出它的类型,因为它的类型取决于您所指的重载。因此,您必须在某个地方手动消除歧义。

如果您可以使用 C++11 功能,您应该编写

std::sort(a.begin(),a.end(),
    [=](vector<int> const& a, vector<int> const& b) {
        return a[n] > b[n];
    } );

摆脱超载问题。在这里,将使用 const 重载只是因为 a 和 b 引用 const 向量。

如果您希望它与 C++98 兼容,另一种选择是编写自己的仿函数来应用下标运算符:

template<class ResultType>
struct apply_subscript {
    typedef ResultType result_type;
    template<class T, class U>
    ResultType operator()(T const& x, U const& y) const { return x[y]; }
    template<class T, class U>
    ResultType operator()(T      & x, U const& y) const { return x[y]; }
};

:::

using namespace boost;
sort(mat.begin(),mat.end(),
    bind(apply_subscript<int>(),_1,n) >
    bind(apply_subscript<int>(),_2,n)
);

高温高压

于 2013-04-28T09:11:04.677 回答
0

我想在这里添加一个 C++11 解决方案,因为在这里使用 Boost 并没有真正获得任何东西。

一个简单的 lambda 解决方案效果最好:std::sort( a.begin(), a.end(), [n]( std::vector< int > first, std::vector< int > second ){ return first[n] < second[n]; } );

使用bind大大增加了问题的复杂性:std::sort( a.begin(), a.end(), std::bind( std::less< int >(), std::bind( static_cast< const int&( std::vector< int >::* )( size_t ) const >( &std::vector< int >::operator[] ), std::placeholders::_1, n ), std::bind( static_cast< const int&( std::vector< int >::* )( size_t ) const >( &std::vector< int >::operator[] ), std::placeholders::_1, n ) );

我不认为有任何理由,但如果你真的很喜欢bindover lambdas,你可以通过这样做来减少讨厌的static_cast事情:

auto columnChooser = std::bind( static_cast< const int&( std::vector< int >::* )( size_t ) const >( &std::vector< int >::operator[] ), std::placeholders::_1, n );
std::sort( a.begin(), a.end(), std::bind( std::less< int >(), columnChooser, columnChooser );
于 2014-09-08T11:09:46.307 回答