4

When I examine some code snip from some libraries, I saw some code like this:

template<typename _Function, typename _ReturnType>
struct _TaskOfType_ContinuationTypeTraits
{
    typedef task<typename _TaskTypeTraits<typename _FunctionTypeTraits<_Function, _ReturnType>::_FuncRetType>::_TaskRetType> _TaskOfType;
};

Can someone provide some explanation of the code? What is it trying to do and what is the advantage to use a struct with only typedef statement within the body?

user2984297
  • 353
  • 1
  • 3
  • 14

2 Answers2

4

In C++ parlance, the _TaskOfType_ContinuationTypeTraits is a metafunction. It does type computations at compile-time.

A metafunction is in a way similar to a run-time function. The key difference is that the input arguments to a metafunction are type(s), and returns are also type(s).

Eg. The following metafunction takes a type, and returns a pointer of the type you supply to it.

template <typename T>
struct add_pointer
{
    typedef T* type;
}

Now, if you did add_pointer<int>::type, it returns int*. You see, you gave it a type (int in this case) and the compiler computed a new type (int* in this case) and gave it back to you when you invoked the ::type of the metafunction. When you do ::type on a metafunction, that is when the template is instantiated. This is the run-time equivalent of calling a function. Also note that all of this happened at compile-time!

Now, going back to your _TaskOfType_ContinuationTypeTraits. This is just like my add_pointer. In add_pointer, I just had one template argument, you have two. I just added a pointer to the type that was supplied, you have something much more complicated. But, at it's essence, it is only a type computation. My add_pointer returns when I call ::type on it, yours does when you call ::_TaskOfType.

The Vivandiere
  • 3,059
  • 3
  • 28
  • 50
  • Nice! Now it has some meat! +1 – Fantastic Mr Fox Aug 17 '16 at 19:09
  • I think your answer is more related in explaining the purpose(advantage) of such syntax. And your example is easier to understand and makes sense too. Eventually it is calculating the type. But @Vittorio Romeo answer makes sense too. – user2984297 Aug 17 '16 at 19:22
1

This kind of syntax is used to create "templated typedefs". In C++11 and above, type aliases / alias templates should be used instead.

The purpose of the code snippet you posted is to create a type alias that depends on _Function and _ReturnType.

It can be accessed like this:

typename _TaskOfType_ContinuationTypeTraits<F, R>::_TaskOfType

If you have access to C++11, this is a cleaner, better and more straightforward solution:

template<typename _Function, typename _ReturnType>
using _TaskOfType = 
    task<typename _TaskTypeTraits<
        typename _FunctionTypeTraits<_Function, _ReturnType>::_FuncRetType>::_TaskRetType>

Which can be used like this:

_TaskOfType<F, R>

More info: "Difference between typedef and C++11 type alias"

Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416