Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decltype, result_of, or typeof?

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.

like image 251
Neil G Avatar asked May 04 '10 08:05

Neil G


People also ask

Is decltype runtime or compile time?

decltype is a compile time evaluation (like sizeof ), and so can only use the static type.

What does decltype stand for?

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 )

Is decltype evaluated?

Like the sizeof operator, decltype 's operand is not evaluated.

Why is std :: Result_of deprecated?

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);


1 Answers

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.

like image 179
Potatoswatter Avatar answered Sep 28 '22 17:09

Potatoswatter