Reputation: 629
I'm trying to sort a two-dimensional array vector<vector<int> > a(M,vector<int>(N))
row-wise with respect to its n-th column like this:
sort(a.begin(),a.end(),
(bind(&vector<int>::operator[],_1,n) >
bind(&vector<int>::operator[],_2,n)));
however my compiler tells me
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)’
how should I resolve the call?
PS.: tried an even simpler version of the preceding access to operator[]
vector<int> a(10);
(bind(&vector<int>::operator[],_1,_2))(a,2);
which is an adapted copy-cut-and-paste directly from Karlsson's book. Getting
error: no matching function for call to ‘bind(<unresolved overloaded function type>, const boost::lambda::placeholder1_type&, const boost::lambda::placeholder2_type&)’
also for that...
Upvotes: 2
Views: 1428
Reputation: 38919
I'd like to add a C++11 solution in here, since you don't really gain anything by using Boost here.
A simple lambda solution would work best: std::sort( a.begin(), a.end(), [n]( std::vector< int > first, std::vector< int > second ){ return first[n] < second[n]; } );
Using bind
largely increases the complexity of the problem: 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 ) );
I don't see any reason to be, but if you're really attached to bind
over lambdas you can minimize the nastiness of the static_cast
by doing this:
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 );
Upvotes: 0
Reputation: 28097
As @soon said, &std::vector<int>::operator[]
refers to an overload set. But you can't pass such a thing to a function template and expect it to deduce its type because its type depends on which overload you meant. So, somewhere you would have to disambiguate it manually.
If you can make use of C++11 features, you should be writing
std::sort(a.begin(),a.end(),
[=](vector<int> const& a, vector<int> const& b) {
return a[n] > b[n];
} );
to get rid of the overloading issue. Here, the const overload would be used simply because a and b refer to const vectors.
If you want it to be C++98 compatible another alternative is to write your own functor for applying the subscript operator:
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
Upvotes: 2
Reputation: 31
With Boost.Phoenix you can use what @sellibitze mentions in the comments:
#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;
}
Upvotes: 3
Reputation: 33671
std::vector
has const
and non-const
versions of operator[]
, and compiler can't deduce, which overloading should be used. You could do something like this:
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;
}
Or, without 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)
);
Output:
3 1 5 1
4 3 4 1
1 2 3 4
9 1 0 2
Upvotes: 2