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.
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
Decltype keyword in C++ Decltype stands for declared type of an entity or the type of an expression. It lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression. SYNTAX : decltype( expression )
Like the sizeof operator, decltype 's operand is not evaluated.
F(Args...) is a function type with Args... being the argument types and F being the return type. As such, std::result_of suffers from several quirks that led to its deprecation in favor of std::invoke_result in C++17: F cannot be a function type or an array type (but can be a reference to them);
Since whatever result you obtain depends on the template parameter, typedef typename
is necessary.
decltype
is a standard C++11 feature. It is an "operator" which takes an expression and returns a type.
typedef typename decltype( T().toCPD() ) D; // can't use T:: as it's nonstatic
If T()
isn't a valid (T
not default-constructible) you will want declval
which is a function that takes a type and returns a meaningless, invalid value of that type. declval
can only be used in unevaluated contexts such as decltype
.
typedef typename decltype( std::declval<T>().toCPD() ) D;
Before C++11, decltype
was a non-standard extension by Microsoft's MSVC compiler. Its behavior might have been changed slightly by standardization.
typeof
is GCC's equivalent pre-C++11 extension like decltype
, which was also cloned in other compilers. Here is its documentation from GCC. That page provides no comparison between the features, but it notes that typeof
must 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_of
is 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 function int(void)
, function pointer int(*)(void)
, functor class implementing operator()
, 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_of
with a pointer to member function, you must include the parent object type in the argument list as a surrogate for this
.
typedef typename std::result_of< decltype( & T::toCPD ) ( T * ) >::type D;
This is very brittle, though, because &T::toCPD
cannot be resolved if there's any overloading, such as a non-const version. This is true despite the fact that T *
or T const *
must be explicitly written out! In most cases, you're better off with decltype
and declval
.
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