[英]What is difference between decltype(auto) and decltype(returning expr) as return type?
[英]What is the type of an 'auto' return type when returning *this in an anonymous class?
在這段代碼中:
struct
{
auto operator[](const char*)
{
return *this;
}
} m_some_class;
這里的auto
類型是什么?
這里的
auto
類型是什么?
類型是decltype(m_some_class)
- 即,返回值與變量m_some_class
的類型相同。
請注意,function 將返回*this
的副本。
如果需要對*this
的引用,您可以使用auto&
或者,因為 C++14,更通用的decltype(auto)
。
對於匿名結構類型,編譯器在內部創建一個名稱,您的情況下的 auto 返回結構。
您可以在下面看到,您的匿名結構被命名為__anon_1_1
並且operator[]
function 返回__anon_1_1
結構的 object。 m_some_class
是__anon_1_1
類型的實例
cppinsights網站提供了一種理解方式
你的代碼
struct
{
auto operator[](const char*)
{
return *this;
}
}m_some_class;
編譯器版本
struct __anon_1_1
{
inline __anon_1_1 operator[](const char *)
{
return __anon_1_1(*this);
}
// inline constexpr __anon_1_1() noexcept = default;
// inline constexpr __anon_1_1(const __anon_1_1 &) noexcept = default;
};
__anon_1_1 m_some_class = __anon_1_1();
給定代碼中的行:
return *this;
返回 struct m_some_class
本身,即operator[]
的類型是:
decltype(m_some_class); // i.e. the type returned is the same as the struct
另外,請注意,這只會返回結構的副本實例,因為傳遞的參數沒有給出任何引用運算符。 對結構副本所做的任何更改都不會影響原始結構。
auto
關鍵字? auto
關鍵字通常用於程序員不知道某物的類型或者輸入太長的情況。
此外,由auto
定義的類型可能會因各種情況而異。 例如:
auto len = vector.size(); // len is now defined as size_t in compile time
在某些系統中, len
的類型可能是unsigned long
,在我的情況下,它是unsigned long long
,在這里你不能明確定義在這個不確定的地方正確使用哪個限定符。 這里我們使用auto
關鍵字。
以下所有標准參考均指N4659:2017 年 3 月 Kona 后工作草案/C++17 DIS 。
class 是匿名的並不重要,因為返回類型僅從return
語句推導出來。
// Denote the type of the anonymous class as 'T'.
// Return type deduced to 'T'
auto operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
auto& operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
decltype(auto) operator[](const char*)
{
return *this;
}
詳情及相關標准段落如下。
auto
(C++11 及更高版本)來自[expr.unary.op]/1 [摘錄,強調我的]:
[expr.unary.op]/1一元
*
運算符執行間接:應用它的表達式應是指向 object 類型的指針,或指向 function 類型的指針,結果是指向 ZA8668CFDE6913114B5 的左值表達式指向的 function。 [...]
因此, *this
的結果是一個左值,它引用了調用操作符調用的 object。
來自[dcl.spec.auto]/1和[dcl.spec.auto]/2 [摘錄,強調我的]:
[dcl.spec.auto]/1
auto
和decltype(auto)
類型說明符用於指定占位符類型,稍后將通過初始化程序的推導來替換該占位符類型。 [...][dcl.spec.auto]/2占位符類型可以與 function 聲明符 [...] 在此類聲明符有效的任何上下文中出現。 [...]如果 function 的聲明返回類型包含占位符類型,則 function 的返回類型是從未丟棄的
return
語句推導出來的[...]。
來自[dcl.type.auto.deduct]/2和[dcl.type.auto.deduct]/4 [摘錄,強調我的]:
[dcl.type.auto.deduct]/2包含占位符類型的類型
T
和相應的初始化器e
確定如下:
- (2.1) 對於出現在 function 中的非丟棄
return
語句,聲明的返回類型包含占位符類型,T
是聲明的返回類型,e
是返回語句的操作數。 如果 return 語句沒有操作數,則e
為void()
;- [...]
[dcl.spec.auto]/4如果占位符是自動類型說明符,則使用模板參數推導規則確定推導的類型
T'
替換T
[...][ 例子:
const auto &i = expr;
i
的類型是下面發明的 function 模板的調用f(expr)
中參數u
的推導類型:template <class U> void f(const U& u);
—結束示例]
因此,成員運算符 function 的返回類型
auto operator[](const char*)
{
return *this;
}
匿名類型,比如T
,是在以下發明的 function 模板的調用f(*this)
中推導出的參數u
類型:
template <class U> void f(U u);
其中,如上所述, *this
是一個左值,因此返回類型推導出為T
; 即匿名 class 的類型。
使用相同的參數,返回成員運算符 function
auto& operator[](const char*)
{
return *this;
}
匿名類型的,比如T
,是T&
。
根據上面的論點,class 是匿名的並不重要,因為返回類型僅從return
語句中推導出來。
decltype(auto)
(C++14 及更高版本) 如果我們用占位符類型decltype(auto)
替換占位符返回類型auto
,則不同的規則控制如何確定返回類型。
decltype(auto) operator[](const char*)
{
return *this;
}
來自[dcl.type.auto.deduct]/5 [摘錄,強調我的]:
如果占位符是
decltype(auto)
類型說明符,則T
應是單獨的占位符。 為T
推導的類型如 [dcl.type.simple] 中所述確定,就好像e
是decltype
的操作數一樣。
而且,從[dcl.type.simple]/4 , [dcl.type.simple]/4.3應用 [extract]:
對於表達式
e
,由decltype(e)
表示的類型定義如下:
- [...]
- (4.4) 否則,如果
e
是左值,則decltype(e)
是T&
,其中T
是e
的類型;
如上所示, e
(返回語句; *this
)是一個左值,並且[dcl.type.simple]/4.1 、 [dcl.type.simple]/4.2和[dcl.type.simple]/4.3 都不適用於此處.
因此,使用decltype(auto)
占位符類型修改的 OP 示例中的返回類型是T&
。
它是T
,其中T
是 class 的未命名類型。
即使它沒有已知名稱,該類型仍然存在,並且可以通過auto
和decltype
等機制“使用”。
不過,您可能想要auto&
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.