为什么函数返回类型中不允许参数推导?



最明显的答案可能是 -因为标准是这样说的。
这很好,但我正在思考它以了解这种选择背后的原因。

请考虑以下示例:

template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}

它无法编译并出现以下错误:

错误:使用类模板"S"需要模板参数;函数返回类型中不允许参数推导

很容易修复,这不是问题,这样的东西就可以了:

auto f() { return S{0}; }

但是,我想了解在函数返回类型中也允许类模板参数推导的缺点是什么。
乍一看,它看起来像一个愚蠢的限制,但我很确定我在这里错过了一些重要的东西。

这里没有任何语言法:如果指定返回类型(而不是autoT,其中T是模板类型(,则该返回类型必须有效。 让我给你一个更简单、更好的例子:

std::vector function() {
return std::vector<int>();
}

显然,即使没有花哨的模板,它也无法编译auto和类型推导,因为std::vector不是一个类型,std::vector<int>是。

当您将S指定为返回类型时,您基本上

  • 阻止编译器推导类型本身
  • 指定无效的返回类型,因为S不是类型,S<int>是。

为什么函数返回类型中不允许参数推导?

因为标准是这么说的。

你可以问这样一个问题:为什么这些代码行之间存在差异:

S s = 0;            // OK
S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0

你可以想出一个挥手的解释,为什么第一个应该没问题,为什么第二个不应该 - 但从根本上说,类模板参数推导被提出来只解决第一种情况,而不是第二种情况。第一个是可以的,因为标准是这样说的,第二个是错误的,因为标准是这样说的。

提出了一个扩展(P1021,在"函数的返回类型推断"下(,以解决第二种情况。不管你是否认为这是一个好主意... ̄\_(ツ)_/̄

只是我挥手的两分钱,总结了我的理解:

S f() { return 0; }

S不是可以推断的类型,它只是一个模板。你可以写

template<typename T>
S<T> f() { return 0;}

但现在很明显,对于一个电话

auto s = f();

没有办法推断T应该是什么类型。

最新更新