【问题标题】:Disable the std::initializer_list constructor禁用 std::initializer_list 构造函数
【发布时间】:2020-02-12 15:10:47
【问题描述】:

我正在尝试确定在某些情况下是否可以禁用 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 构造函数。

【问题讨论】:

    标签: c++


    【解决方案1】:

    我想弄清楚是否可以完全禁用 initializer_list 构造函数?

    你不能。这就是语言的工作方式,如果您使用了大括号初始化并且您有一个 std::initializer_list 构造函数,那么它就是一个被调用的构造函数。

    您可以做的是删除允许首先创建std::initializer_list 的隐式转换。如果你使expr::operator bool() explicit 然后e 不能转换为bool 这意味着现在唯一合适的重载是my_vec(expr e)

    【讨论】:

      【解决方案2】:

      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 }
      {}
      

      LIVE

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-31
        • 2014-09-21
        • 1970-01-01
        • 2013-10-29
        • 2022-11-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多