未评估的操作数和自动返回类型

时间:2016-08-18 22:15:49

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

根据[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 必须进行评估才能知道实际的返回类型是什么。

因为我很确定工作草案是对的,问题是:我的推理出了什么问题?

2 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:1)

  

在这种情况下,它仍然可以被视为未评估的操作数吗?一世   意思是,在我看来,在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 ,函数的返回类型是从非丢弃中推导出来的   函数体中的return语句(如果有的话)

关于占位符类型扣除

  

<强> [dcl.type.auto.deduct/1]   占位符类型扣除是包含a的类型的过程   占位符类型由推断类型替换。

扣除占位符返回类型:

  

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

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