为什么函数 return 类型不允许参数推导?
Why isn't argument deduction allowed in function return type?
最明显的答案可能是 - 因为标准是这么说的。
没关系,但我正在绞尽脑汁想了解这个选择背后的原因。
考虑以下示例:
template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}
编译失败,错误如下:
error: use of class template 'S' requires template arguments; argument deduction not allowed in function return type
很容易修复,这不是问题,像这样的东西很好用:
auto f() { return S{0}; }
但是,我想了解在函数 return 类型中也允许 class 模板参数推导的缺点是什么。
乍一看,它看起来像是一个愚蠢的限制,但我很确定我在这里遗漏了一些重要的东西。
这里没有任何语言法律问题:如果您指定 return 类型(而不是 auto
或 T
,其中 T
是模板类型),那么 return 类型必须有效。让我给你一个更简单、更好的例子:
std::vector function() {
return std::vector<int>();
}
显然它无法编译,即使没有花哨的模板,auto
和类型推导,因为 std::vector
不是类型,std::vector<int>
是。
当您将 S
指定为 return 类型时,您基本上
- 防止编译器推导类型本身
- 指定无效的 return 类型,因为
S
不是类型,S<int>
是。
只是我手挥的两分钱总结了我的理解:
在
S f() { return 0; }
S
不是可以推导的类型,它只是一个模板。你可以写
template<typename T>
S<T> f() { return 0;}
但现在很明显,为了一个电话
auto s = f();
无法推断 T
应该是什么类型。
Why isn't argument deduction allowed in function return type?
因为标准是这么说的。
您可能会问这个问题:为什么这些代码行之间存在差异:
S s = 0; // OK
S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0
你可以想出一个简单的解释为什么第一个应该没问题,为什么第二个不应该 - 但从根本上说 class 模板参数推导被提议只解决第一种情况而不是第二。第一个没问题,因为标准是这么说的,第二个是错误的,因为标准是这么说的。
有一个扩展提议(P1021,在 "Return type deduction for functions" 下)将解决第二种情况。不管你认为这是个好主意...¯\_(ツ)_/¯
最明显的答案可能是 - 因为标准是这么说的。
没关系,但我正在绞尽脑汁想了解这个选择背后的原因。
考虑以下示例:
template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}
编译失败,错误如下:
error: use of class template 'S' requires template arguments; argument deduction not allowed in function return type
很容易修复,这不是问题,像这样的东西很好用:
auto f() { return S{0}; }
但是,我想了解在函数 return 类型中也允许 class 模板参数推导的缺点是什么。
乍一看,它看起来像是一个愚蠢的限制,但我很确定我在这里遗漏了一些重要的东西。
这里没有任何语言法律问题:如果您指定 return 类型(而不是 auto
或 T
,其中 T
是模板类型),那么 return 类型必须有效。让我给你一个更简单、更好的例子:
std::vector function() {
return std::vector<int>();
}
显然它无法编译,即使没有花哨的模板,auto
和类型推导,因为 std::vector
不是类型,std::vector<int>
是。
当您将 S
指定为 return 类型时,您基本上
- 防止编译器推导类型本身
- 指定无效的 return 类型,因为
S
不是类型,S<int>
是。
只是我手挥的两分钱总结了我的理解:
在
S f() { return 0; }
S
不是可以推导的类型,它只是一个模板。你可以写
template<typename T>
S<T> f() { return 0;}
但现在很明显,为了一个电话
auto s = f();
无法推断 T
应该是什么类型。
Why isn't argument deduction allowed in function return type?
因为标准是这么说的。
您可能会问这个问题:为什么这些代码行之间存在差异:
S s = 0; // OK
S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0
你可以想出一个简单的解释为什么第一个应该没问题,为什么第二个不应该 - 但从根本上说 class 模板参数推导被提议只解决第一种情况而不是第二。第一个没问题,因为标准是这么说的,第二个是错误的,因为标准是这么说的。
有一个扩展提议(P1021,在 "Return type deduction for functions" 下)将解决第二种情况。不管你认为这是个好主意...¯\_(ツ)_/¯