簡體   English   中英

重載 oeprator[] 的使用不明確

[英]Use of overloaded oeprator[] is ambiguous

簡化代碼如下:

#include <string>
#include <string_view>

struct object{
  operator std::string(){return "";}
}

struct foo{
  foo operator[](std::string_view s){
    return foo{};
  }
  
  template <typename T>
  operator T(){
    return object{};
  }
};

int main(){
  foo f;
  std::string s = f["a"];
}

clang 給出錯誤:

 error: use of overloaded oeprator '[]' is ambiguous (with oeprand types 'foo' and 'const char*') note: candidate function foo operator[](std::string_view s) note: built-in candidate operator[](long, const char*) note: built-in candidate operator[](long, const volatile char*)

但 gcc 成功編譯上述代碼。

clang 版本為 12.0.1,gcc 為 7.5.0

我很困惑,哪個編譯器是正確的?

template <typename T> operator T(){ return object{}; }

我認為 clang 在這里是正確的,因為這個片段使foo class 可以轉換為任何類型,並且應該在重載決議發揮作用之前實例化可行的模板函數

在重載決議開始之前,通過名稱查找和模板參數推導選擇的函數組合起來形成候選函數集

如您所見,重載與以下 arguments: (long, const char*)相沖突,因此它必須是類似於此3["a"]表達式,根據cppreference是完全合法的:

 expr1 [ expr2 ]

對於內置運算符,其中一個表達式( expr1expr2 )必須是“ T數組”類型的泛左值或“指向 T 的指針”類型的純右值,而另一個表達式(分別為expr2expr1 )必須是無作用域枚舉或整數類型的純右值。 此表達式的結果類型為T


然而,它也提供了如何區分內置下標和自定義重載的線索:

 expr1 [ { expr, ... } ]

方括號內帶有大括號的列表的形式僅用於調用重載的operator[]

所以如果上述例子是這樣寫的,你應該很好:

int main(){
    foo f;
    std::string s = f[{"a"}];
    return 0;
}

或者將下標顯式轉換為字符串,因此編譯器不會將其與 arrays 的內置運算符混淆:

int main(){
    using namespace std::string_literals;
    
    foo f;
    std::string s = f["a"s];
    return 0;
}

暫無
暫無

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

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