簡體   English   中英

禁用 std::initializer_list 構造函數

[英]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() explicite不能轉換為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.

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