簡體   English   中英

始終使用構造函數而不是顯式轉換運算符

[英]Constructor is always used instead of explicit conversion operator

我有以下課程:

template <typename T1>
class Foo {
public:
    Foo(T1* obj) : obj(obj) {}

    template <typename T2>
    Foo(const Foo<T2>& other) : obj(other.obj) {}

    template <typename T2>
    explicit operator Foo<T2>() {
        return Foo<T2>(static_cast<T2*>(obj));
    }
    T1* obj;
};

第二個構造函數的意圖是,如果允許從X*Y*的隱式轉換,則允許從Foo<X>Foo<Y>的隱式轉換。

轉換運算符允許使用從X*Y*的顯式轉換從Foo<X>Foo<Y>的顯式轉換。

但我注意到轉換運算符永遠不會被使用。 即使我進行顯式轉換,編譯器也總是使用第二個構造函數。 如果無法隱式轉換基礎類型,則會導致錯誤。

以下代碼可用於測試上面的類。

class X {};
class Y : public X {};

int main() {
    Y obj;
    Foo<Y> y(&obj);
    Foo<X> x = y; // implicit cast works as expected.
    // y = x; // implicit conversion fails (as expected).
    // y = static_cast<Foo<Y>>(x); // conversion fails because constructor is
                                   // called instead of conversion operator.
}

有沒有辦法讓編譯器使用轉換運算符進行顯式轉換?

對於static_cast<Foo<Y>>(x); ,你試圖直接從x (它是一個Foo<X> )構造一個Foo<Y> ,對於這樣的上下文,轉換構造函數優先於轉換函數

(強調我的)

如果轉換函數和轉換構造函數都可用於執行某些用戶定義的轉換,則轉換函數和構造函數都會在復制初始化和引用初始化上下文中通過重載解析來考慮 ,但在直接初始化上下文中只考慮構造函數

 struct To { To() = default; To(const struct From&) {} // converting constructor }; struct From { operator To() const {return To();} // conversion function }; int main() { From f; To t1(f); // direct-initialization: calls the constructor // (note, if converting constructor is not available, implicit copy constructor // will be selected, and conversion function will be called to prepare its argument) To t2 = f; // copy-initialization: ambiguous // (note, if conversion function is from a non-const type, eg // From::operator To();, it will be selected instead of the ctor in this case) To t3 = static_cast<To>(f); // direct-initialization: calls the constructor const To& r = f; // reference-initialization: ambiguous } 

您可以通過SFINAE使轉換構造函數從此案例的重載集中丟棄; 即只有在允許底層指針的隱式轉換時才使其有效。

template <typename T2, typename = std::enable_if_t<std::is_convertible<T2*, T1*>::value>>
Foo(const Foo<T2>& other) : obj(other.obj) {}

生活

請查看標准中的以下引用

靜態演員 [expr.static.cast / 4]

一個表達式e可以顯式轉換到類型T使用static_cast形式static_cast<T>(e) ,如果聲明T t(e); 是良好的 ,對一些發明臨時變量t (8.5)。 這種顯式轉換的效果與執行聲明和初始化,然后使用臨時變量作為轉換結果相同。 當且僅當初始化將其用作左值時,表達式e用作glvalue。

這基本上說構造函數優於轉換運算符,這就是發生的情況。

暫無
暫無

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

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