Ori*_*ent 13 c++ decltype auto c++14
如果在两种情况下都没有使用括号,那么函数(模板)的返回类型decltype(auto)和decltype(returning expression)返回类型之间有什么区别expr?
auto f() -> decltype(auto) { return expr; } // 1
auto f() -> decltype(expr) { return expr; } // 2
Run Code Online (Sandbox Code Playgroud)
上面f可以在任何上下文中定义/声明,可以是(成员)函数或(成员)函数模板,甚至是(泛型)lambda.expr可以依赖于任何模板参数.
在第二个版本中,两者expr都是完全相同的表达式,没有额外的括号.
在C++ 14及更高版本中使用第一种或第二种形式可以预期哪些差异?
如果括号到处使用怎么办?
Gui*_*cot 15
是,有一点不同.第一个将根据函数体中的返回表达式检测返回类型.
第二个也不会将返回类型设置为内部表达式的类型decltype(),但也会在其上应用表达式sfinae.这意味着如果decltype中的表达式无效,编译器将搜索另一个有效的重载.而第一个版本将是一个硬错误.
举个例子:
template<typename T>
auto fun(T a) -> decltype(a.f()) { return a.f(); }
template<typename T>
auto fun(T a) -> decltype(a.g()) { return a.g(); }
struct SomeType {
int g() { return 0; }
};
fun(SomeType{});
Run Code Online (Sandbox Code Playgroud)
这选择了正确的过载.现在,如果我们替换decltype(expr)为decltype(auto),编译器将无法选择正确的重载,因为函数签名中没有任何内容限制类型应该能够执行的操作.
decltype(auto) 习惯了
在通用代码中转发返回类型,你不想输入很多重复的东西
template<class Func, class... Args>
decltype(auto) foo(Func f, Args&&... args)
{
return f(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)延迟类型扣除,正如你在这个问题中看到的,编译器有一些问题decltype(auto)
template<int i> struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i> constexpr auto iter(Int<i>) -> decltype(iter(Int<i-1>{}));
int main(){
decltype(iter(Int<10>{})) a;
}
Run Code Online (Sandbox Code Playgroud)这可以很好地工作,你可以在这里看到:
template<int i> struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) {
return iter(Int<i-1>{});
}
int main(){
decltype(iter(Int<10>{})) a;
}
Run Code Online (Sandbox Code Playgroud)decltype(expr):
decltype(auto)不是