簡體   English   中英

GCC 無法區分 operator++() 和 operator++(int)

[英]GCC can't differentiate between operator++() and operator++(int)

template <typename CRTP>
struct Pre {
    CRTP & operator++();
};

template <typename CRTP>
struct Post {
    CRTP operator++(int);
};

struct Derived
    : Pre<Derived>
    , Post<Derived>
{};

int main() {
    Derived d;
    d++;
    ++d;
}

我從 GCC 收到這些錯誤:

<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
        d++;
        ^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
        CRTP operator++(int);
            ^~~~~~~~
<source>:3:16: note:                 CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
        CRTP & operator++();
                ^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
        ++d;
        ^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
        CRTP operator++(int);
            ^~~~~~~~
<source>:3:16: note:                 CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
        CRTP & operator++();
                ^~~~~~~~

前自減和后自減運算符會導致類似的錯誤。 Clang 沒有這樣的錯誤。 任何想法可能是錯誤的或如何解決這個問題?

名稱查找必須首先發生。 在這種情況下,名稱為operator++

[basic.lookup] (強調我的)

1名稱查找規則統一適用於語法允許的所有名稱(包括 typedef-names ([dcl.typedef])、namespace-names ([basic.namespace]) 和 class-names ([class.name]))特定規則討論的上下文中的此類名稱。 名稱查找將名稱的使用與該名稱的聲明 ([basic.def]) 相關聯。 名稱查找應為名稱找到一個明確的聲明(參見 [class.member.lookup]) 如果名稱查找發現名稱是函數名稱,則名稱查找可能會將多個聲明與名稱相關聯; 聲明被稱為形成一組重載函數([over.load])。 重載解析 ([over.match]) 在名稱查找成功后發生 僅在名稱查找和函數重載解析(如果適用)成功后才考慮訪問規則(條款 [class.access])。 只有在名稱查找、函數重載解析(如果適用)和訪問檢查成功之后,名稱聲明引入的屬性才會進一步用於表達式處理(條款 [expr])。

並且只有當查找是明確的時,才會進行重載解析。 在這種情況下,名稱位於兩個不同類的范圍內,因此即使在重載解析之前也存在歧義。

[類.成員.查找]

8如果明確找到重載函數的名稱,重載解析([over.match])也會在訪問控制之前發生。 歧義通常可以通過用類名限定名稱來解決。 [ 例子:

 struct A { int f(); }; struct B { int f(); }; struct C : A, B { int f() { return A::f() + B::f(); } };

— 結束示例 ]

該示例幾乎總結了 [class.member.lookup] 前面段落中相當長的查找規則。 您的代碼中存在歧義。 GCC 報告它是正確的。


至於解決這個問題,評論中的人已經提出了解決方法的想法。 添加輔助 CRTP 類

template <class CRTP>
struct PrePost
    : Pre<CRTP>
    , Post<CRTP>
{
    using Pre<CRTP>::operator++;
    using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};

該名稱現在位於單個類的范圍內,並命名了兩個重載。 查找成功,可以進行重載解析。

暫無
暫無

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

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