Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I properly write trailing return type?

Suppose I have this function template:

template<typename T1, typename T2>
auto DoSomething(const T1& arg);

Of course this function needs a trailing return type which, considering the function's purpose, I really could not get right.

What this function is supposed to do is to use arg, do some operation with arg and a T2 object and use the result of that operation as the return value of the function. Clearly, DoSomething()'s return type must (compatibly) match with the return type of the operation done for arg and the T2 object.

Suppose again that we make DoSomething() do some real operation, like multiplication. We would then write DoSomething() as like the code below:

template<typename T1, typename T2>
auto DoSomething(const T1& arg) -> /* trailing return-type */ {
    T2 t2Obj;   // Or have it obtained in some other way
    return arg * t2Obj;
}

How should I then form the trailing return-type for this?


P.S.: I've tried using decltype(arg * T2), decltype(T1 * T2) and decltype(T1::operator * (T2)) and some other really bizarre-looking decltypes for the trailing-return type. None of them worked.

like image 298
Mark Garcia Avatar asked Dec 29 '12 08:12

Mark Garcia


1 Answers

You should use decltype and std::declval<> as:

template<typename T1, typename T2>
auto DoSomething(const T1& arg) -> decltype(arg * std::declval<T2>())
{
    T2 t2Obj;   // Or have it obtained in some other way
    return arg * t2Obj;
}

because T2 might not have default constructor, so decltype(arg *T2()) may not work.

But then I also notice that if T2 doesn't have default constructor, then you would not be able to write T2 t2Obj either. So if you require T2 to have default constructor, then you can simply write this:

-> decltype(arg *T2()) //requirement : T2 must have default constructor

that should also work if you require T2 to have default constructor!

like image 167
Nawaz Avatar answered Sep 20 '22 14:09

Nawaz