Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why decltype is used in trailing return types?

consider the following codes:

template< class T1 , class T2>
auto calc( T1 a , T2 b )
{
   return a + b ;
}


template< class T1 , class T2>
auto calc( T1 a , T2 b ) -> decltype( a + b )
{
   return a + b ;
}

Whats the difference in the second code ? Can you give some example where this makes a difference or does it make a difference here ?

like image 757
Sunny Shah Avatar asked Sep 25 '15 11:09

Sunny Shah


People also ask

Why use trailing return type?

The trailing return type feature removes a C++ limitation where the return type of a function template cannot be generalized if the return type depends on the types of the function arguments.

What does decltype return?

decltype returnsIf what we pass to decltype is the name of a variable (e.g. decltype(x) above) or function or denotes a member of an object ( decltype x.i ), then the result is the type of whatever this refers to. As the example of decltype(y) above shows, this includes reference, const and volatile specifiers.

What does decltype auto do?

decltype(auto) is primarily useful for deducing the return type of forwarding functions and similar wrappers, where you want the type to exactly “track” some expression you're invoking.


1 Answers

Note that the plain auto return type is something that is only for C++14, whereas the trailing return type with decltype is for C++11. The difference comes when references enter the picture, e.g. in code like this:

#include <type_traits>

struct Test
{
    int& data;

    auto calc1()
    {
       return data;
    }

    auto calc2() -> decltype(data)
    {
       return data;
    }
};

int main()
{
    int x;
    Test t{x};
    static_assert(std::is_same<int, decltype(t.calc1())>::value, "");
    static_assert(std::is_same<int&, decltype(t.calc2())>::value, "");
}

If you want to remove ->decltype() and keep your code behaving the same, you can use the C++14 construct decltype(auto)

decltype(auto) calc3() // same as calc2() above
{
    return data;
}

which preserves the referenceness of the return type as well.

If you already know that your return type is a reference, just make it explicit

auto& calc4() // same as calc2() above
{
    return data;
}
like image 180
TemplateRex Avatar answered Oct 12 '22 12:10

TemplateRex