[英]Why is this user-defined conversion not done?
考慮:
template<typename T>
struct Prop
{
T value;
operator T() { return value; }
};
int main()
{
Prop<float> p1 { 5 };
Prop<std::vector<float>> p2 { { 1, 2, 3 } };
float f1 = p1; // Works fine
float f2_1_1 = p2.value[0]; // Works fine
float f2_1_2 = p2[0]; // Doesn't compile
return 0;
}
為什么標記為這樣的行不能編譯? 它不應該使用提供的轉換運算符執行隱式轉換為std::vector<>
,以便可以找到[]
嗎?
該網站上還有(許多)其他問題,要求對此問題有所不同,但我找不到我認為適用於此的問題。 它與std::vector
是模板有關嗎?
成員函數調用的對象(包括下標運算符重載)不考慮隱式轉換。
請考慮是否允許這樣做的后果:每次像這樣調用任何未聲明的成員函數時,編譯器都必須弄清楚該對象可以轉換為的所有類型(請注意,其他任何其他不相關的類型都可以具有轉換構造函數),並檢查是否已聲明缺少成員函數。 更不用說這會對代碼閱讀器造成多大的混亂(在您的轉換運算符情況下,轉換可能很明顯,但在轉換構造函數的情況下卻不明顯,據我所知,它們在其他方面沒有不同的對待)。
那么有沒有一種符號上方便的方法可以使Prop表現出我想要的方式
您必須為要透明傳遞的vector的每個成員函數定義一個成員函數。 下面是下標運算符的示例:
auto operator[](std::size_t pos) {
return value[pos];
}
auto operator[](std::size_t pos) const {
return value[pos];
}
問題當然是必須明確聲明所有包裝的成員函數。 另一個問題是類型取決於T
參數。 例如, vector::operator[]
使用vector::size_type
,可能沒有為您可能使用的所有T
定義(肯定不是為float
)。 在這里,我們做出妥協,並使用std::size_t
。
創建這種“透明”包裝的一種較省力的方法是繼承。 一個公共繼承的模板將自動具有父對象的所有成員函數,並且可以隱式轉換為它,並且可以由父類型的指針和引用來引用。 但是,這種方法的透明度有點問題,主要是因為~vector
不是虛擬的。
私有繼承允許與您的成員方法相同的包裝,但是語法好得多:
template<typename T>
struct Prop : private T
{
using T::operator[];
using T::T;
};
請注意,繼承方法阻止您將基本類型用作T
另外,它使隱式轉換成為不可能(即使使用轉換運算符也是如此),因此您不能在期望T
自由函數中將Prop
用作T
PS。 請注意,轉換運算符返回一個值,因此必須復制向量,這可能是不希望的。 考慮改為提供參考版本:
operator T&&()&& { return *this; }
operator T&()& { return *this; }
operator const T&() const& { return *this; }
與任何
p2.size();
p2.begin();
p2.push_back(24);
// etc.
編譯沒有意義
也
p2[0];
相當於
p2.operator[](0);
編譯沒有意義\\
如果您想要這種行為(即讓Prop<T>
借用 T
成員),則Bjarne提出了C ++提議,將點運算符添加到語言中。 我將以與operator- ->
用於智能指針的方式相同的方式工作。 事發時有很多爭議,所以我不會為此屏住呼吸。
操作員點(R3)-Bjarne Stroustrup,Gabriel Dos Rei
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.