简体   繁体   English

在另一个成员函数的尾随返回类型中获得推断成员函数的decltype是否格式良好?

[英]Is getting the decltype of a deduced member function inside the trailing return type of another member function well-formed?

Whoever is saying that this question is a duplicate of the question " Is there a specific reason why a trailing-return-type is not a complete-class context of a class? " does not know what he/she is talking about. 无论谁说这个问题都是一个问题的重复“ 是否有一个特定的原因,为什么一个尾随返回类型不是一个完整的类的背景? ”并不知道他/她在说什么。 The fact that a trailing return type is not a complete-class context of a class does not explain why the code in this question doesn't compile, although it explains the rejection of the code given in the answer to the other question, specially the part of the code involving the member functions qux and baz , as explained by the OP. 尾随返回类型不是类的完整类上下文的事实并不能解释为什么这个问题中的代码不能编译,尽管它解释了对另一个问题的答案中给出的代码的拒绝,特别是如OP所解释的,涉及成员函数quxbaz的代码的一部分。

In order to clarify my argument that the code below is valid, you have to take into consideration the second note in [expr.prim.this] which says: In a trailing-return-type, the class being defined is not required to be complete for purposes of class member access. 为了澄清我的论点,即下面的代码是有效的,你必须考虑[expr.prim.this]中的第二个注释 ,它说: 在trailing-return-type中,被定义的类不需要是完成以便访问类成员。 Class members declared later are not visible. 稍后声明的类成员不可见。 As foo is declared before bar in my example, there is nothing to prevent the compiler from accessing foo in the trailing-return-type of bar . 由于foo在我的示例中在bar之前声明,因此没有什么可以阻止编译器在trailing-return-type bar访问foo

Note that the comment below by @NathanOliver is based on the conjecture that the inline definition for the member function foo below is just syntactic sugar. 请注意@AathanOliver 下面的注释是基于下面的成员函数 foo的内联定义只是语法糖的猜想。 This needs to be proven from a quote in the Standard. 这需要从标准中的引用证明。 I haven't found that yet . 我还没有找到 Once that quote is produced, I will certainly accept an answer arguing that the code doesn't compile because a trailing-return-type is not a complete-class context of a class. 一旦产生了这个引用,我肯定会接受一个答案,认为代码没有编译,因为trailing-return-type不是类的完整类上下文。

struct Test {
        auto foo() {}                       
        auto bar() -> decltype(foo()) {}
    };

prog.cc:3:32: error: use of 'auto Test::foo()' before deduction of 'auto'
    3 |     auto bar() -> decltype(foo()) {}
      |                                ^
prog.cc:3:32: error: use of 'auto Test::foo()' before deduction of 'auto'

[dcl.spec.auto]/9 : [dcl.spec.auto] / 9

If a function with a declared return type that uses a placeholder type has no non-discarded return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body. 如果具有使用占位符类型的声明的返回类型的函数没有非丢弃的返回语句,则推断返回类型,就好像在函数体的右括号处没有操作数的return语句一样。 [ Example: [例如:

auto f() { } // OK, return type is void

auto* g() { } // error, cannot deduce auto* from void()

— end example ] - 结束例子]

[dcl.type.auto.deduct]/(2.1) : [dcl.type.auto.deduct] /(2.1)

A type T containing a placeholder type, and a corresponding initializer e , are determined as follows: 包含占位符类型的类型T和相应的初始化程序e确定如下:

(2.1) for a non-discarded return statement that occurs in a function declared with a return type that contains a placeholder type, T is the declared return type and e is the operand of the return statement. (2.1)对于在使用包含占位符类型的返回类型声明的函数中发生的非废弃返回语句, T是声明的返回类型, e是return语句的操作数。 If the return statement has no operand, then e is void() ; 如果return语句没有操作数,则evoid() ;

(2.2) for a variable declared with a type that contains a placeholder type, T is the declared type of the variable and e is the initializer. (2.2)对于使用包含占位符类型的类型声明的变量,T是变量的声明类型,e是初始值设定项。 If the initialization is direct-list-initialization, the initializer shall be a braced-init-list containing only a single assignment-expression and e is the assignment-expression; 如果初始化是直接列表初始化,则初始化器应该是一个braced-init-list,只包含一个赋值表达式,e是赋值表达式;

(2.3) for a non-type template parameter declared with a type that contains a placeholder type, T is the declared type of the non-type template parameter and e is the corresponding template argument. (2.3)对于使用包含占位符类型的类型声明的非类型模板参数,T是非类型模板参数的声明类型,e是相应的模板参数。

According to [dcl.spec.auto]/9 and [dcl.type.auto.deduct]/(2.1) the code should compile. 根据[dcl.spec.auto] / 9和[dcl.type.auto.deduct] /(2.1),代码应该编译。 But GCC and cland reject it. GCC和支持者拒绝了它。 What am I missing? 我错过了什么?

 struct Test { auto foo() { /*1*/ } auto bar() -> decltype(foo()) {} }; 

At marker 1, the name Test::bar is in scope along with all other members of struct Test . 在标记1处,名称Test::barstruct Test所有其他成员一起在范围内。 Therefore the compiler cannot analyze the body of foo() until the class is complete. 因此,在类完成之前,编译器无法分析foo()的主体。

We then have a partial ordering: 然后我们有一个部分订购:

  • Parse body of Test::foo() before deducing its return type 在推断其返回类型之前,解析Test::foo()主体
  • Complete class Test before parsing body of Test::foo() 在解析Test::foo()主体之前完成类Test
  • Analyze trailing return type of Test::bar() before completing class Test (from the question you pled is not a dupe) 在完成类Test之前分析尾随返回类型的Test::bar() (从您提出的问题不是欺骗)

and by transitivity, the return type of Test::bar() must be analyzed without yet performing return type deduction for Test::foo() . 并且通过传递性,必须在不对Test::foo()执行返回类型推导的情况下分析Test::bar()返回类型。


Since a Standard quote was requested, here it is from [class.mem] : 由于要求标准报价,所以它来自[class.mem]

A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier . 一类被认为是在闭合完全定义的对象类型(或完整的类型) }类指定符 Within the class member-specification , the class is regarded as complete within function bodies , default arguments, noexcept-specifiers , and default member initializers (including such things in nested classes). 在类成员规范中该类在函数体 ,默认参数, noexcept-specifiers和默认成员初始化器(包括嵌套类中的这类事物)中被视为完整 Otherwise it is regarded as incomplete within its own class member-specification. 否则,它在其自己的类成员规范中被视为不完整。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 获取成员函数的decltype? - Getting the decltype of a member function? decltype作为类成员函数中的返回类型 - decltype as a return type in class member function 使用decltype和constness的C ++ 11尾随返回成员函数 - C++11 trailing return member function using decltype and constness 格式良好的程序包含格式错误的模板成员函数? - Well-formed program containing an ill-formed template member function? 在将decltype与带有尾随返回类型语法的模板化成员函数一起使用时,gcc中出现编译器错误,但没有clang - compiler error in gcc but not clang when using decltype with templated member function with trailing return type syntax 在通用lambda中使用`if constexpr`访问成员类型需要两个分支都是格式良好的 - gcc vs clang - Accessing member type with `if constexpr` inside generic lambda requires both branches to be well-formed - gcc vs clang decltype和成员函数(不是指针)类型 - decltype and member function (not pointer) type 推导出的返回类型依赖于成员 function 模板参数 - deduced return type depedent on member function template argument 为什么类模板的成员函数声明必须格式正确? - Why should the member function declarations of a class template be all well-formed? 具有编译器删除的默认特殊成员函数的格式良好的类定义的示例 - An example of a well-formed class definition with a defaulted special member function that the compiler makes deleted
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM