[英]Conditional class template constructor
我試圖使一個具有條件成員的類如下(示例代碼來說明問題):
template<bool b>
struct conditional_members {};
template<>
struct conditional_members<true>
{ int m; };
template<typename T, bool b>
struct my_class : public conditional_members<b>
{
T n;
// constructor for case when b is false
my_class(T n) : n(n) {};
// constructor for case when b is true
my_class(T n, int m) : n(n), m(m) {};
};
我需要根據bool b
有兩個條件構造函數,但這不能編譯。 我試着用bool值專門化構造函數:
template<typename T>
my_class<T, true>::my_class(T n, int m) : n(n), m(m) {};
template<typename T>
my_class<T, false>::my_class(T n) : n(n) {};
但這不能編譯,因為不允許部分函數模板專門化。
有沒有辦法做到這一點?
問題所在
// constructor for case when b is true
my_class(T n, int m) : n(n), m(m) {};
是構造函數的mem-initializer-list只能命名虛擬基類,直接基類和直接非靜態數據成員,而不能命名像m
這樣的繼承成員。 這是因為基類的成員是由基類子對象構造函數初始化的,因此無法再次初始化(盡管可以對其進行分配)。
您可以改為指定基類初始化程序。 在此示例中, conditional_members
是一個聚合,因此聚合初始化將起作用:
// constructor for case when b is true
my_class(T n, int m) : n(n), conditional_members<b>{m} {};
盡管這樣,您可能會因my_class
專業化始終聲明了兩個構造函數而產生一些奇怪的副作用,即使實際上實例化一個構造函數或另一個構造函數可能無效。
這是一個SFINAE技巧,使構造函數有條件地有效地不可見,具體取決於b
:
#include <type_traits>
// Define conditional_members as before.
template<typename T, bool b>
class my_class : public conditional_members<b>
{
T n;
public:
// constructor for case when b is false
template <typename = std::enable_if_t<!b>>
my_class(T n) : n(n) {}
// constructor for case when b is true
template <typename = std::enable_if_t<b>>
my_class(T n, int m) : conditional_members<b>{m}, n(n) {}
};
作為預覽,在具有C ++ 20約束的情況下,您將可以使用這種更好,更簡單的方法來編寫它:
template<typename T, bool b>
class my_class : public conditional_members<b>
{
T n;
public:
// constructor for case when b is false
my_class(T n) requires(!b) : n(n) {}
// constructor for case when b is true
my_class(T n, int m) requires(b) : conditional_members<b>{m}, n(n) {}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.