I've written some code which counts the number of elements of vector using a functor and the ref and bind templates from boost:: or std:: (for C++11) namespaces. I'm using a #define to switch between boost:: and std:: namespaces. I'm using boost version 1.53  and my compilation command is g++ test.cpp -std=c++11. I've tried with gcc versions 4.7.2 and 4.6.3 and I get the same errors with both.
I have 3 questions:
std and boost versions of bind, ref and function? (I saw this question but the answers don't mention ref or function)Thanks!
P.S. The example just illustrates my problem, I know about size() for std::vector :-)
//#define USE_STD
#ifdef USE_STD
#include <functional>
using namespace std::placeholders;
namespace impl = std;
#else
#include <boost/version.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace impl = boost;
#endif
#include <iostream>
#include <algorithm>
#include <vector>
class Item {
    int id_;
public:
    Item(int id) : id_(id) {};
};
template <typename ITEM>
class Counter {
    int count_;
public:
    // typedef void result_type; // adding this fixes Example 3 when impl=boost
    Counter() : count_(0) {};
    void operator()(ITEM* item) {count_++;}
    int operator()() {return count_;}
};
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#ifndef USE_STD
    std::cout << "BOOST_LIB_VERSION=" << BOOST_LIB_VERSION << std::endl;
#endif
    // allocate
    typedef std::vector<Item*> ItemVec;
    ItemVec vec;
    for (int i = 0; i < 9; ++i) {vec.push_back(new Item(i));}
    // Example 1, works for BOTH
    Counter<Item> f1;
    f1 = std::for_each(vec.begin(), vec.end(), f1);
    std::cout << "f1()=" << f1() << std::endl;
    // Example 2, works with impl=std ONLY
    // COMPILE ERROR with impl=boost: "no match for call to ‘(boost::reference_wrapper<Counter<Item> >) (Item*&)’"
    Counter<Item> f2;
    std::for_each(vec.begin(), vec.end(), impl::ref(f2));
    std::cout << "f2()=" <<  f2() << std::endl;
    // Example 3, works with impl=std ONLY
    // COMPILE ERROR with impl=boost "no type named ‘result_type’ in ‘class Counter<Item>’"
    // this can fixed by adding the typedef described above
    Counter<Item> f3;
    std::for_each(vec.begin(), vec.end(), impl::bind(impl::ref(f3), _1));
    std::cout << "f3()=" << f3() << std::endl;
    // clean up
    for (ItemVec::iterator it = vec.begin(); it != vec.end(); ++it) {
        delete *it;
    }
    vec.clear();
    return 0;
}
                Example 2 fails because boost::reference_wrapper doesn't have a member operator() which forwards the argument(s), unlike std::reference_wrapper. As such, it's only useful for passing normal arguments by reference, not functions or functors which are expected to be called.
Example 3 fails because Boost.Bind relies on a specific protocol to get the result type of the function or functor you pass, if you use the version without explicit return type. If you pass it a pointer-to-function or pointer-to-member-function, the returnd binder object has a nested result_type set to the return type of said PTF or PTMF. If you pass a functor, it needs a nested result_type.std::bind, on the other hand, simply has no nested result_type if your functor doesn't have one.
Note that you can, as I said, explicitly provide the result type to both boost::bind and std::bind:
std::for_each(vec.begin(), vec.end(), impl::bind<void>(impl::ref(f3), _1));
//                                              ^^^^^^
Which fixes the example and makes it compile.
std::ref has 1 major advantage over boost::ref:  It provides a varadic perfect-forwarding operator(), which will forward the call onto its contained reference.  
boost::ref can't practically do this, as it would require a significant number of overloads.  To allow this, however, boost::bind (and a few other classes) all provide special handling for boost::reference_wrapper.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With