簡體   English   中英

為什么未完成此用戶定義的轉換?

[英]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- ->用於智能指針的方式相同的方式工作。 事發時有很多爭議,所以我不會為此屏住呼吸。

運營商點建議的背景知識-Bjarne Stroustrup

操作員點(R3​​)-Bjarne Stroustrup,Gabriel Dos Rei

通過委派進行智能引用:N4477運營商點的替代選擇-Hubert Tong,費薩爾·瓦利(Faisal Vali)

運算符點的替代方法-Bjarne Stroustrup

暫無
暫無

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

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