[英]C++ base class constructor taking derived class as argument (?)
用例:
Vector
類(實現一些數學)和一個派生的Vector2D
類 Vector
namespace mu {
template<std::size_t N, typename T>
class Vector {
public:
// ...
template <typename... TArgs>
Vector(TArgs... args) : data({args...}) {}
Vector(const Vector &other) = default; // copy constructor
// ...
protected:
std::array<T, N> data;
};
}
Vector2D
namespace mu {
template<typename T>
class Vector2D : public Vector<2,T> {
public:
using Vector<2, T>::Vector; // inherit base class constructors
Vector2D(const Vector<2, T>& other) : Vector<2, T>(other) {}
// Vector2D specific functions, e.g. rotation
//...
};
}
注意:實際的類包含更多內容,但我將其濃縮為我認為在這里最重要的代碼。
問題是我無法實現一種可以從Vector2D
構造Vector
的Vector2D
,請參閱下面的代碼。 所有其他情況都可以正常工作。
// Example 1 (compiles)
mu::Vector<2, int> a{1, 2};
mu::Vector<2, int> b{a};
// Example 2 (compiles)
mu::Vector2D<int> c{1, 2};
mu::Vector2D<int> d{c};
// Example 3 (compiles)
mu::Vector<2, int> e{1, 2};
mu::Vector2D<int> f{e};
// Example 4 (doesn't compile) <-- how to get this to work?
mu::Vector2D<int> g{1, 2};
mu::Vector<2, int> h{g};
當然,更普遍的問題是繼承是否是構建這些類的正確方法。 但是我希望Vector2D
具有Vector
所有功能以及Vector
沒有的附加功能。
您的Vector
類有兩個構造函數:一個模板(用於值)和默認的復制構造函數。
問題:復制構造函數是首選,但前提是存在完全匹配。
所以,用a
初始化b
mu::Vector<2, int> a{1, 2};
mu::Vector<2, int> b{a};
首選復制構造函數,因為a
是完全匹配的
但是,用g
初始化h
mu::Vector2D<int> g{1, 2};
mu::Vector<2, int> h{g};
g
可以轉換為mu::Vector<2, int>
但不是完全匹配,因此模板構造函數是首選,但模板構造函數不兼容。
一種可能的解決方案:當只有一個參數並且該參數從mu::Vector
派生時,SFINAE 禁用模板構造函數。
例如
template <typename... TArgs,
typename std::enable_if_t<sizeof...(TArgs) == N
or (not std::is_base_of_v<Vector, TArgs> && ...), int> = 0>
Vector(TArgs const & ... args) : data({args...}) {}
撇開繼承對這個特定任務的適用性不談,失敗的直接原因是template <typename... TArgs>
構造函數。 它將攔截每個不是副本的構造——並且從派生類對象構造不是副本。 這是因為從 Derived 到 Base 的轉換是一種轉換,而模板構造函數不需要轉換,所以是更好的匹配。
如果參數適合構造std::array
成員,您希望將全部構造函數限制為僅包含在重載決議中。 這是 SFINAE 的標准應用程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.