Steve Emmerson Steve Emmerson - 1 month ago 13
C++ Question

How to declare return type of C++ template method to be that of static method in other class?

I want to do the valid C++11 equivalent of the following (apparently) invalid code:

class StaticMethodClass {
public:
static int staticMethod(int a) {return 0;}
};

#include <type_traits>

template<class T> class ClassTemplate {
public:
decltype(T::staticMethod(int)) methodTemplate(int a);
};

template<class T>
decltype(T::staticMethod(int)) ClassTemplate<T>::methodTemplate(int a) {
return T::staticMethod(a);
}

template class ClassTemplate<StaticMethodClass>;


I get the following errors from my compiler:

/tmp$ g++ -std=c++11 -c a.cpp
a.cpp:14:26: error: expected primary-expression before ‘int’
decltype(T::staticMethod(int)) ClassTemplate<T>::methodTemplate(int a) {
^
a.cpp:14:32: error: prototype for ‘decltype (T:: staticMethod(<expression error>)) ClassTemplate<T>::methodTemplate(int)’ does not match any in class ‘ClassTemplate<T>’
decltype(T::staticMethod(int)) ClassTemplate<T>::methodTemplate(int a) {
^
a.cpp:10:36: error: candidate is: int ClassTemplate<T>::methodTemplate(int)
decltype(T::staticMethod(int)) methodTemplate(int a);
^
/tmp$ g++ -dumpversion
4.8.3


Is what I want to do possible? If so, how?

Answer

I don't think std::result_of works this way. It's defined as result_of<F(ArgTypes...)> (see cppreference). That F argument should be a type. When you write T::staticMethod you are giving result_of the function, not the type.

F must be a callable type, reference to function, or reference to callable type. Invoking F with ArgTypes... must be a well-formed expression.

So what you want is to give result_of the type of the reference to that function. A pointer to that function is given by &T::staticMethod, and its type by decltype(&T::staticMethod). This code works.

typename std::result_of<decltype(&T::staticMethod)(int)>::type methodTemplate(int i) {
    return T::staticMethod(i);
}

Also note typename as pointed out by Chris.

Comments