[英]Is getting the decltype of a deduced member function inside the trailing return type of another member function well-formed?
無論誰說這個問題都是一個問題的重復“ 是否有一個特定的原因,為什么一個尾隨返回類型不是一個完整的類的背景? ”並不知道他/她在說什么。 尾隨返回類型不是類的完整類上下文的事實並不能解釋為什么這個問題中的代碼不能編譯,盡管它解釋了對另一個問題的答案中給出的代碼的拒絕,特別是如OP所解釋的,涉及成員函數qux
和baz
的代碼的一部分。
為了澄清我的論點,即下面的代碼是有效的,你必須考慮[expr.prim.this]中的第二個注釋 ,它說: 在trailing-return-type中,被定義的類不需要是完成以便訪問類成員。 稍后聲明的類成員不可見。 由於foo
在我的示例中在bar
之前聲明,因此沒有什么可以阻止編譯器在trailing-return-type bar
訪問foo
。
請注意@AathanOliver
下面的注釋是基於下面的成員函數
foo
的內聯定義只是語法糖的猜想。
這需要從標准中的引用證明。
我還沒有找到 。
一旦產生了這個引用,我肯定會接受一個答案,認為代碼沒有編譯,因為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'
如果具有使用占位符類型的聲明的返回類型的函數沒有非丟棄的返回語句,則推斷返回類型,就好像在函數體的右括號處沒有操作數的return語句一樣。 [例如:
auto f() { } // OK, return type is void
auto* g() { } // error, cannot deduce auto* from void()
- 結束例子]
[dcl.type.auto.deduct] /(2.1) :
包含占位符類型的類型
T
和相應的初始化程序e
確定如下:(2.1)對於在使用包含占位符類型的返回類型聲明的函數中發生的非廢棄返回語句,
T
是聲明的返回類型,e
是return語句的操作數。 如果return語句沒有操作數,則e
為void()
;(2.2)對於使用包含占位符類型的類型聲明的變量,T是變量的聲明類型,e是初始值設定項。 如果初始化是直接列表初始化,則初始化器應該是一個braced-init-list,只包含一個賦值表達式,e是賦值表達式;
(2.3)對於使用包含占位符類型的類型聲明的非類型模板參數,T是非類型模板參數的聲明類型,e是相應的模板參數。
根據[dcl.spec.auto] / 9和[dcl.type.auto.deduct] /(2.1),代碼應該編譯。 但GCC和支持者拒絕了它。 我錯過了什么?
struct Test { auto foo() { /*1*/ } auto bar() -> decltype(foo()) {} };
在標記1處,名稱Test::bar
與struct Test
所有其他成員一起在范圍內。 因此,在類完成之前,編譯器無法分析foo()
的主體。
然后我們有一個部分訂購:
Test::foo()
主體 Test::foo()
主體之前完成類Test
Test
之前分析尾隨返回類型的Test::bar()
(從您提出的問題不是欺騙) 並且通過傳遞性,必須在不對Test::foo()
執行返回類型推導的情況下分析Test::bar()
返回類型。
由於要求標准報價,所以它來自[class.mem]
:
一類被認為是在閉合完全定義的對象類型(或完整的類型)
}
的類指定符 。 在類成員規范中 , 該類在函數體 ,默認參數, noexcept-specifiers和默認成員初始化器(包括嵌套類中的這類事物)中被視為完整 。 否則,它在其自己的類成員規范中被視為不完整。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.