Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
533 views
in Technique[技术] by (71.8m points)

c++ - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...