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 ?
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.
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.
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With