【问题标题】:Why isn't argument deduction allowed in function return type?为什么函数返回类型中不允许参数推导?
【发布时间】:2018-05-31 10:36:05
【问题描述】:

最明显的答案可能是 - 因为标准是这样说的
没关系,但我正在仔细研究它以了解此选择背后的原因。

考虑以下示例:

template<typename T>
struct S { S(T) {} };

S f() { return 0; }

int main() {
    auto s = f();
    (void)s;
}

编译失败,出现如下错误:

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

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

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

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

【问题讨论】:

  • 我觉得不规范,因为这种代码写起来容易,但读起来很难看懂(实际用的是什么类型)。标准编写器主要包括基于最佳实践的功能,而您的示例似乎使编写代码更加困难。
  • 但您现在几乎可以做到这一点 - 使用 lambdas。
  • @BhavinChirag 我同意。几乎。毕竟使用auto 作为返回类型并不是更明确。

标签: c++ templates language-lawyer c++17 template-argument-deduction


【解决方案1】:

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

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

显然它无法编译,即使没有花哨的模板,auto 和类型推导,因为std::vector 不是类型,std::vector&lt;int&gt; 是。

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

  • 防止编译器自行推断类型
  • 指定无效的返回类型,因为S 不是类型,S&lt;int&gt; 是。

【讨论】:

  • 我认为你找到了最好的例子来说明这一点。非常感谢。确实很简单,但是我没找到重点。
【解决方案2】:

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

因为标准是这样说的。

你可能会问:为什么这几行代码有区别:

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

您可以对为什么第一个应该可以以及为什么第二个不应该提出一个手动解释 - 但从根本上说,类模板参数推导只针对第一种情况而不是第二种情况。第一个是可以的,因为标准是这样说的,第二个是错误的,因为标准是这样的。

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

【讨论】:

  • 从技术上讲,标准并没有说不允许。它只是没有说它是。 :-D
【解决方案3】:

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

S f() { return 0; }

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

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

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

auto s = f();

无法推断T 应该是什么类型。

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多