[英]Disable the std::initializer_list constructor
我正在嘗試確定在某些情況下是否可以禁用 std::initializer_list 構造函數。 我正在編寫一個支持表達式(數學和關系運算符)的自定義向量類。 關系表達式隱式轉換為 bool 以允許在 if 語句中使用,但在某些情況下,我希望從關系表達式中獲得向量結果,這會導致我的向量類 (v5) 的構造函數出現問題。
#include <vector>
struct expr
{
std::size_t size() const { return 1; }
auto at(std::size_t i) const { return 1.0; }
operator bool() const { return true; }
};
template<typename T>
struct my_vec
{
my_vec(std::initializer_list<T> init)
: vec_{ init }
{}
my_vec(std::size_t sz)
: vec_( sz )
{}
my_vec(expr e)
: vec_( e.size() )
{
for (std::size_t i = 0; i != e.size(); ++i) vec_.at(i) = e.at(i);
}
std::vector<T> vec_;
};
void test_init_a(void)
{
// initialize_list constructor
my_vec<double> v1{ 1.0 };
my_vec<double> v2{ 1.0, 2.0 };
// size_t constructor
my_vec<double> v3(5);
// expression constructors
expr e;
my_vec<double> v4( e );
my_vec<double> v5{ e }; // <-- this one attempts the initializer_list constructor because of the implicit cast to bool and fails due to narrowing
}
我總是可以使用括號從表達式 (v4) 中構造我的向量,但我想弄清楚是否可以完全禁用 initializer_list 構造函數?
我嘗試過對 initializer_list 實現一個包裝器並使用雙括號初始化,但是這會導致單元素訪問問題(v1),因為它嘗試使用 size_t 構造函數而不是 initializer_list 構造函數。
我想弄清楚是否可以完全禁用 initializer_list 構造函數?
你不能。 這就是語言的工作方式,如果您使用了花括號初始化並且您有一個std::initializer_list
構造函數,那么它就是一個被調用的構造函數。
不過,您可以做的是刪除允許首先創建std::initializer_list
的隱式轉換。 如果您使expr::operator bool()
explicit
則e
不能轉換為bool
,這意味着現在唯一合適的重載是my_vec(expr e)
作為解決方法,您可以制作構造函數模板,然后在std::initializer_list
的類型與類的模板參數T
不同時應用 SFINAE 使其不可用。
template <typename X, std::enable_if_t<std::is_same_v<X, T>>* = nullptr>
my_vec(std::initializer_list<X> init)
: vec_{ init }
{}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.