簡體   English   中英

在匿名 class 中返回 *this 時,“自動”返回類型的類型是什么?

[英]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


TLDR:占位符返回類型扣除

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 autodecltype(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 語句沒有操作數,則evoid()
  • [...]

[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] 中所述確定,就好像edecltype的操作數一樣

而且,從[dcl.type.simple]/4[dcl.type.simple]/4.3應用 [extract]:

對於表達式e ,由decltype(e)表示的類型定義如下:

  • [...]
  • (4.4) 否則,如果e是左值,則decltype(e)T& ,其中Te的類型;

如上所示, e (返回語句; *this )是一個左值,並且[dcl.type.simple]/4.1[dcl.type.simple]/4.2[dcl.type.simple]/4.3 都不適用於此處.

因此,使用decltype(auto)占位符類型修改的 OP 示例中的返回類型是T&

它是T ,其中T是 class 的未命名類型。

即使它沒有已知名稱,該類型仍然存在,並且可以通過autodecltype等機制“使用”。

不過,您可能想要auto&

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM