【问题标题】:Unevaluated operands and auto return type未计算的操作数和自动返回类型
【发布时间】:2016-08-18 22:15:49
【问题描述】:

根据[5/8][7.1.7.2/4](工作草案):

  • decltype 说明符的操作数是未计算的操作数
  • 未计算的操作数未计算

考虑下面的代码:

#include<type_traits>

struct S { using type = int; };

int f(int i);

template<typename T>
typename T::type g(T);

template<typename T>
auto h(T v) { return v; }

int main() {
    static_assert(std::is_same<decltype(f(42)), int>::value, "!");
    static_assert(std::is_same<decltype(g(S{})), int>::value, "!");
    static_assert(std::is_same<decltype(h(42)), int>::value, "!");
}

不用说,fg 实际上并没有被评估。
另一方面,函数h 有一个auto 返回类型,它是从它的主体推导出来的,因此是从它的参数推导出来的,因此是从推导的类型T 推导出来的。

在这种情况下,它是否仍可被视为未计算的操作数
我的意思是,在我看来,在 decltype 的上下文中,必须评估函数 h 才能知道实际的返回类型是什么。

因为我很确定工作草案是正确的,所以问题是:我的推理有什么问题?

【问题讨论】:

  • 查看此问题的一种方法是:编译器是否需要知道 v 的什么值才能从 h(42) 推断出 T,或者只是 v 的类型?

标签: c++ c++14 auto decltype


【解决方案1】:

为了确定decltype(h(42))所表示的类型,编译器需要对h进行模板实参推导并实例化模板特化h&lt;int&gt;以检查其主体并确定返回类型。这与评估h(42) 相同;例如,如果h 包含打印消息等任何副作用,则不会发生这些副作用。

【讨论】:

  • 你的回答让我觉得很傻! :-) ... 在谈到函数时,我曾经认为未计算的操作数不需要定义的东西。实际上,关键部分是它们未评估,即使在示例中的情况下也是如此。一旦以这种方式解释,它就有意义了。谢谢你。 :-)
【解决方案2】:

在这种情况下,它是否仍可被视为未计算的操作数?一世 意思是,在我看来,在 decltype 的上下文中, 必须评估函数 h 才能知道实际的返回类型是什么。

它仍然是一个未评估的上下文。正如Brain's answer(这是较短的答案)所解释的那样。

C++ 标准讨论了模板参数推导过程,以及用参数替换函数模板: [temp.deduct/7] (强调我的)

替换发生在所有使用的类型和表达式中 函数类型和模板参数声明。这 表达式不仅包括常量表达式,例如 出现在数组边界或作为非类型模板参数但也 sizeof 中的一般表达式(即非常量表达式), decltype,以及其他允许非常量表达式的上下文。 替换按词汇顺序进行,当满足条件时停止 导致扣除失败。

您可以从the first paragraph 开始阅读以获取有关模板参数推导的更多详细信息。


如果你有兴趣,我们可以关注短篇小说

(注:所有引用段落均为部分转载,点击部分链接查看完整段落)

由于您已经了解decltype未评估的上下文,并且已经引用了相关部分,我们可以跳过这些并从auto 开始...

[dcl.spec.auto/1]: autodecltype(auto) 类型说明符用于指定一个 占位符类型,稍后将通过从 初始化器....

来自占位符类型的视图:

[dcl.spec.auto/2]: 占位符类型可以与函数声明符一起出现... ... 如果函数声明的返回类型包含 占位符 type,函数的返回类型是从non-discarded推导出来的 return 函数体中的语句(如果有)

关于占位符类型扣除

[dcl.type.auto.deduct/1]: 占位符类型推导是一个类型包含一个 占位符类型被推导类型替换。

推导占位符返回类型:

[type.auto.deduct/4]: 如果占位符是自动类型说明符,则推导类型T' 替换 T 是使用 template 参数的规则确定的 扣除

如果故事不是很清楚,您可能需要阅读每个引用段落的完整部分。

【讨论】:

    猜你喜欢
    • 2021-09-09
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2013-02-03
    • 2013-06-12
    相关资源
    最近更新 更多