最明显的答案可能是 - ,因为标准是这样说的。 那很好,但是我绕着它去理解这个选择背后的原因。
考虑以下示例:
template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}
无法编译错误,如:
错误:使用课程模板&#39; S&#39;需要模板参数;函数返回类型中不允许使用参数推导
很容易解决,这不是一个问题,像这样的工作正常:
auto f() { return S{0}; }
但是,我想了解在函数返回类型中允许类模板参数推导的缺点是什么。
乍一看,它看起来就像一个愚蠢的限制,但我很确定我在这里缺少一些重要的东西。
答案 0 :(得分:10)
这里没有语言规则:如果您指定了返回类型(而不是auto
或T
其中T
是模板类型),则该返回类型具有有效。让我给你一个更简单,更好的例子:
std::vector function() {
return std::vector<int>();
}
显然,即使没有花哨的模板,也无法编译auto
和类型扣减,因为std::vector
不是类型,std::vector<int>
是。
当您指定S
作为返回类型时,基本上
S
不属于S<int>
类型。答案 1 :(得分:5)
为什么函数返回类型中不允许参数推导?
因为标准是这样说的。
你可以问一个问题:为什么这些代码行之间存在差异:
S s = 0; // OK
S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0
你可以想出一个手写的解释,为什么第一个应该没问题,为什么第二个不应该 - 但基本上,类模板参数推导被提议只解决第一个案例而不是第二个案例。第一个是好的,因为标准是这样说的,第二个是错误,因为标准是这样说的。
有一个扩展建议(P1021,在“函数的返回类型扣除”下,将解决第二种情况。你是否认为这是一个好主意...¯\ _(ツ)_ /¯
答案 2 :(得分:4)
只是我的手工波浪两分钱总结了我的理解:
在
S f() { return 0; }
S
不是可以推断的类型,它只是一个模板。你可以写
template<typename T>
S<T> f() { return 0;}
但现在很明显,对于一个电话
auto s = f();
没有办法推断出T
应该是什么类型。