I have:
class A {
public:
B toCPD() const;
And:
template<typename T>
class Ev {
public:
typedef result_of(T::toCPD()) D;
After instantiating Ev<A>, the compiler says:
meta.h:12: error: ‘T::toCPD’ is not a type
neither decltype nor typeof work either.
Since whatever result you obtain depends on the template parameter,
typedef typenameis necessary.decltypeis a standard C++11 feature. It is an “operator” which takes an expression and returns a type.If
T()isn’t a valid (Tnot default-constructible) you will wantdeclvalwhich is a function that takes a type and returns a meaningless, invalid value of that type.declvalcan only be used in unevaluated contexts such asdecltype.Before C++11,
decltypewas a non-standard extension by Microsoft’s MSVC compiler. Its behavior might have been changed slightly by standardization.typeofis GCC’s equivalent pre-C++11 extension likedecltype, which was also cloned in other compilers. Here is its documentation from GCC. That page provides no comparison between the features, but it notes thattypeofmust be called__typeof__when using a standard mode (-std=c++YY, which you should always do), and it is available in C as well as C++.For the sake of C compatibility,
__typeof__will not resolve a reference type from a glvalue expression. So, it’s really only suitable for C. This probably explains why the C++ feature didn’t inherit the more self-explanatory name: GNU was unwilling to sacrifice backward compatibility, whereas Microsoft cares less about C and perhaps needed fewer changes.result_ofis a C++11 metafunction (previously standardized in the ISO TR1 library from 2006). It is a template which takes a callable type (such as a functionint(void), function pointerint(*)(void), functor class implementingoperator(), or pointer-to-member-function&T::toCPD) and an argument type-list for that type, and provides the return type if the call would work.To use
result_ofwith a pointer to member function, you must include the parent object type in the argument list as a surrogate forthis.This is very brittle, though, because
&T::toCPDcannot be resolved if there’s any overloading, such as a non-const version. This is true despite the fact thatT *orT const *must be explicitly written out! In most cases, you’re better off withdecltypeanddeclval.