Below test1.cpp compiles, but test2.cpp does not.  The only difference between the two is that I define Handle::add_it within the class declaration in test1.cpp, but outside in test2.cpp.  
test1.cpp: g++ test1.cpp -o test1 -std=c++11
#include <iostream>
template<typename B>
class Handle
{
public:
        decltype(B.operator(int)) add_it(int x)
        {
                return b(x);
        }
        B b;
};
struct Add1
{
        int operator()(int x)
        {
                return x + 1;
        }
};
int main()
{
        Handle<Add1> h;
        std::cout << h.add_it(5) << std::endl;
}
test2.cpp: g++ test2.cpp -o test2 -std=c++11
#include <iostream>
template<typename B>
class Handle
{
public:
        decltype(B.operator(int)) add_it(int x);
        B b;
};
template<typename B>
decltype(B.operator(int)) Handle<B>::add_it(int x)
{
        return b(x);
}
struct Add1
{
        int operator()(int x)
        {
                return x + 1;
        }
};
int main()
{
        Handle<Add1> h;
        std::cout << h.add_it(5) << std::endl;
}
Errors
test2.cpp:13:11: error: expected primary-expression before ‘.’ token
 decltype(B.operator(int))
           ^
test2.cpp:13:20: error: expected type-specifier before ‘(’ token
 decltype(B.operator(int))
                    ^
test2.cpp:13:21: error: expected primary-expression before ‘int’
 decltype(B.operator(int))
                Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.
In C++11, you can use the decltype type specifier on a trailing return type, together with the auto keyword, to declare a template function whose return type depends on the types of its template arguments.
auto is a keyword in C++11 and later that is used for automatic type deduction. The decltype type specifier yields the type of a specified expression. Unlike auto that deduces types based on values being assigned to the variable, decltype deduces the type from an expression passed to it.
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
You can amend this by using std::declval:
template<typename B>
class Handle
{
public:
  decltype(std::declval<B>()(int())) add_it(int x) {
    return b(x);
  }
  B b;
};
Live Demo
Or outside the definition of the class:
template<typename B>
class Handle {
public:
  decltype(std::declval<B>()(int())) add_it(int x);
  B b;
};
template<typename B>
decltype(std::declval<B>()(int())) Handle<B>::add_it(int x) {
  return b(x);
}
Live Demo
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