Search code examples
c++c++11stdboost-bind

C++11: return_type (for std::bind) of functor where return type is based on input type


I'm playing with functor composition, where the return type of a functor depends on the input type:

template<typename V>
class F
{
protected:
    V v_;
public:
    using return_type = ?;

    F(V v) : v_(v) {}

    template<typename T>
    typename T::U operator()(T t)
    {
        v.method(t);
    }
};

...

X x;
Y y;
F<X> f(x);
F<Y> g(y);
auto h = std::bind(f, std::bind(g, _1));
h(...);  // problem is here :(

Is it possible to find return_type using decltype so that std::bind will work? If so, how?

Edit: I replace U<T> with typename T::U because the return type depends on the type. I hope this is clearer now.

Edit 2 (4?): Added a compilable example that reproduces the problem.

#include <functional>

using namespace std::placeholders;

template<typename I>
struct R
{
    using IT = I;
    R(I x, I y) : b(x), e(y) {}
    I b;
    I e;
};

template<typename IN, typename II>
class CI
{
    CI(II i) {}
};

template<typename IN>
class C
{
    template<typename IR>
    R<CI<IN, typename IR::IT> >
    operator()(IR& i)
    {
        return R<CI<IN, typename IR::IT> >(
            CI<IN, typename IR::IT>(i.b),
            CI<IN, typename IR::IT>(i.e));
    }
};

struct F {};
struct G {};
struct H {};

int main(int argc, char* argv[])
{
    C<F> a;
    C<G> b;
    auto c = std::bind(a, std::bind(b, _1));
    R<H> r{H{}, H{}};
    c(r);
}

Solution

  • Forget about using std::bind for a minute and just try the direct approach:

    C<F> a;
    C<G> b;
    R<H> r{H{}, H{}};
    a(b(r));
    

    This won't even compile, so there's no way the bind version will!

    b(r) isn't valid because of an access violation, and if you fix that a(b(r)) fails because you try to bind a temporary to a non-const lvalue-reference