Hi Miklós,

Sorry for missing your first email.

Miklós Tóth wrote:
Hi!

I have a problem with std::mem_fun_ref and boost::tuple. Here is my code:
I have small LevelSetter class. It makes a level vector indexed by a transform_iterator value.
 
<snip code>

 
When I try to compile i get:

error: call of overloaded 'mem_fun_ref(<unresolved overloaded function type>)' is ambiguous candidates are: c:\mingw-4.6\bin\..\lib\gcc\i686-pc-mingw32\4.6.1\..\..\..\..\include\c++\4.6.1\bits\stl_function.h:697: std::mem_fun_ref_t<_Ret, _Tp> std::mem_fun_ref(_Ret (_Tp::*)()) [with _Ret = int&, _Tp = boost::tuples::cons<int, boost::tuples::cons<float, boost::tuples::null_type> >] c:\mingw-4.6\bin\..\lib\gcc\i686-pc-mingw32\4.6.1\..\..\..\..\include\c++\4.6.1\bits\stl_function.h:702: std::const_mem_fun_ref_t<_Ret, _Tp> std::mem_fun_ref(_Ret (_Tp::*)()const) [with _Ret = const int&, _Tp = boost::tuples::cons<int, boost::tuples::cons<float, boost::tuples::null_type> >]

What am I missing?
 Those problems are usually due to the compiler not knowing which overload of the function to use.  That can be solved using a static_cast (the bind documentation explains it pretty well [1])

Here's a solution that casts appropriately:

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/tuple/tuple.hpp>
#include <functional>
#include <iostream>
#include <vector>

using boost::adaptors::transformed;

void print(int i)
{ std::cout << i << std::endl; }

int main()
{
  typedef boost::tuple<int, float> Tuple;
  std::vector<Tuple> v;
  v.push_back(Tuple(5, 4.));
  v.push_back(Tuple(6, 3.));
  v.push_back(Tuple(7, 2.));

  boost::for_each(v | transformed(std::mem_fun_ref(
    static_cast<int& (Tuple::*)()>(&Tuple::get<0>))), print);
}

(It should work the same with transform_iterator, since I believe transformed eventually just forwards to it.)

To avoid casting, you might consider the following, using fusion and phoenix:

#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/phoenix.hpp>
#include <boost/phoenix/fusion/at.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/tuple/tuple.hpp>
#include <iostream>
#include <vector>

using boost::adaptors::transformed;
namespace px = boost::phoenix;
using px::arg_names::_1;

void print(int i)
{ std::cout << i << std::endl; }

int main()
{
  typedef boost::tuple<int, float> Tuple;
  std::vector<Tuple> v;
  v.push_back(Tuple(5, 4.));
  v.push_back(Tuple(6, 3.));
  v.push_back(Tuple(7, 2.));

  boost::for_each(v | transformed(px::at_c<0>(_1)), &print);
}

HTH,
Nate


[1] <http://www.boost.org/doc/libs/1_54_0/libs/bind/bind.html#err_overloaded>