提升绑定到operator []

时间:2013-04-28 06:59:00

标签: c++ sorting boost matrix bind

我正在尝试按照第n列的顺序排列一个二维数组vector<vector<int> > a(M,vector<int>(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);

直接来自Karlsson的书,是一个改编的复制剪切和粘贴。获得

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

也是为了......

4 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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

答案 2 :(得分: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)
);

HTH

答案 3 :(得分: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 ) );

我认为没有任何理由,但是如果你真的依赖于bind而不是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 );