推导的返回类型对 SFINAE 不友好。如果出现以下情况,该过载将简单地退出过载设置:t[i]
是无效的:
template<typename T>
auto access(T& t, int i)
-> decltype(t[i])
{
return t[i];
}
而此重载则不会,从而导致硬错误:
template<typename T>
decltype(auto) access(T& t, int i)
{
return t[i];
}
Demo https://godbolt.org/z/XuQX3c
此外,您可能会遇到推导的返回类型冲突的问题。考虑一下我是否想退货std::optional<T>
。以下代码无法编译std::nullopt_t
与以下类型不同std::optional<T>
:
#include <optional> // C++17 standard library feature
template <typename T>
auto foo(T const& val)
{
if (val.is_invalid()) return std::nullopt;
return val.some_function_returning_an_optional();
}
尾随返回类型可让您准确指定要返回的表达式类型:
template <typename T>
auto foo(T const& val)
-> decltype(val.some_function_returning_an_optional())
{
if (val.is_invalid()) return std::nullopt;
return val.some_function_returning_an_optional();
}
您可以使用前导返回类型,但这需要使用std::declval
,这使得它更难理解:
template <typename T>
decltype(std::declval<T const&>().some_function_returning_an_optional())
foo(T const& val)
{
if (val.is_invalid()) return std::nullopt;
return val.some_function_returning_an_optional();
}
Demo https://godbolt.org/z/dRA1hH