c++templatesc++03tr1result-of

result_of of call to member function of template parameter


I need to get the result of a member function of a template parameter of a class. Unfortunately, I am bound to C++03 and cannot use decltype, but I can use tr1::result_of. I tried the following code, but that did not work with my compiler (gcc 4.3, I also cannot change this):

#include <tr1/functional>

struct ReturnType {};

struct O 
{
      ReturnType f();
};

template<typename T> struct A
{
      typename std::tr1::result_of<(&T::f)(T*)>::type f();
};

void f()
{
      A<O> a;
      ReturnType x = a.f();
}

The above code reflects my understanding of result_of<Fn(ArgTypes ...):

If Fn is a pointer to a non-static member function, and the first type in ArgTypes is the class the member belongs to (or a reference to it, or a reference to a derived type, or a pointer to it), and the remaining types in ArgTypes describe its arguments.

I pass it a pointer to a member function and specify the first parameter type to be a pointer to the class. However, the compiler prints the following error:

result_of.cpp:12: error: `&' cannot appear in a constant-expression
result_of.cpp:12: error: a function call cannot appear in a constant-expression
result_of.cpp:12: error: template argument 1 is invalid
result_of.cpp:12: error: invalid use of ‘::’
result_of.cpp:12: error: expected ‘;’ before ‘f’
result_of.cpp: In function ‘void f()’:
result_of.cpp:18: error: ‘struct A<O>’ has no member named ‘f’

I cannot change the class O to e.g. add a result typedef, so I must be able to get the return type at compile time.


Solution

  • The std::tr1::result_of requires a type parameter. You are passing it a non-type (a pointer to member).

    This makes std::tr1::result_of very limited in the absence of decltype. For instance you can use it in a wrapper function:

    template <typename Ct, typename Arg>
    void some_wrapper(Ct fun, Arg arg)
    {
        typedef typename std::tr1::result_of<Ct(Arg)>::type ret;
        ret result = fun(arg);
        // ... do something with result
    }
    

    but you cannot use it like you are trying to.