Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tr1::mem_fn and tr1::bind: on const-correctness and overloading

What's wrong with the following snippet ?

#include <tr1/functional>
#include <functional>
#include <iostream>

using namespace std::tr1::placeholders;

struct abc
{
    typedef void result_type;

    void hello(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void hello(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

int
main(int argc, char *argv[])
{
    const abc x;
    int a = 1;

    std::tr1::bind(&abc::hello, x , _1)(a);
    return 0;
}

Trying to compile it with g++-4.3, it seems that cv-qualifier overloaded functions confuse both tr1::mem_fn<> and tr1::bind<> and it comes out the following error:

no matching function for call to ‘bind(<unresolved overloaded function type>,...

Instead the following snippet compiles but seems to break the const-correctness:

struct abc
{
    typedef void result_type;

    void operator()(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void operator()(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

...

    const abc x;
    int a = 1;
    std::tr1::bind( x , _1)(a);

Any clue?

like image 537
Nicola Bonelli Avatar asked Nov 21 '08 21:11

Nicola Bonelli


1 Answers

The lookup is done at a time when the constness of this is not known. You just have to give it a hint via casting. Try this:

typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);

You may also notice here that removing the const still works. This is because you should be passing x by pointer (because the first argument to a C++ member function, the implicit this parameter, is always a pointer). Try this instead:

typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);

As discovered during within my comments below, if you omit the & as you originally did, you'll be passing x by value, which is usually not what you want (though it makes little practical difference in your particular example). This actually seems like an unfortunate pitfall for bind.

like image 127
John Zwinck Avatar answered Oct 08 '22 22:10

John Zwinck