【问题标题】:Can I force a user to provide a value for a member when using designated initializers?使用指定的初始值设定项时,我可以强制用户为成员提供值吗?
【发布时间】:2019-11-02 00:29:00
【问题描述】:

我创建了一个 options 结构体,旨在通过指定的初始化程序使用:

struct FooOptions {
    bool enableReticulation;
};

void Foo(FooOptions&& opts);

Foo(FooOptions{.enableReticulation = true});

不幸的是,因为bool 有一个默认构造函数,这样做也是有效的:

Foo(FooOptions{});

但我不想要这个;我希望 Foo 的用户明确决定是否启用网状结构。我可以通过这种方式通过运行时错误来实现这一点:

struct FooOptions {
    bool enableReticulation = []() -> bool { 
        assert(false, "No value provided for enableReticulation");
    }();
};

但我更愿意使用编译时错误来执行此操作。有没有办法做到这一点?如有必要,我可以将bool 更改为SomeWrapper<bool>,只要我可以像T 一样初始化SomeWrapper<T>,但没有默认初始化程序。

【问题讨论】:

  • 当然,这正是您执行此操作的方法,方法是使用带有非默认构造函数的包装器类型。正如让-卢克·皮卡德上尉所说:做到这一点。
  • 问题是我希望SomeWrapper<T> 可以以所有T 可以构造的方式构造,except 默认构造。对于像bool 这样的简单类型,这很容易,但是如果我有SomeWrapper<std::vector<int>>,我希望能够使用std::initializer_list<int>、一对迭代器、一个分配器以及std::vector 的所有其他方式进行初始化已初始化。
  • 您可以对第二个参数使用可变参数模板并完美转发所有参数
  • 所以?要么委托构造函数,并明确地delete 默认构造函数,要么使用具有至少一个参数的转发构造函数。
  • 我已经尝试了一些没有成功的事情:(我要么得到多个重载解析为相同的类型,这是无效的,要么我最终得到的包装器仍然是默认可构造的,用于空参数包。

标签: c++ initialization designated-initializer


【解决方案1】:

您澄清说这是关于任意类,而不是原始类型。对于任意类,带有任意构造函数:只需删除构造函数,但显式delete默认构造函数:

template<typename T> class SomeWrapper : public T {

    SomeWrapper()=delete;

    using T::T;
};

然后:

#include <vector>

foo F{ {1,2} }; // Works, initializes the vector with {1,2}

foo G{}; // Fails

对于原始类型,这可能不像您想要的那样工作。只需根据需要专门化SomeWrapper。没有那么多原始类型需要处理。

【讨论】:

  • 谢谢!幸运的是,就我而言,我只关心原始类型的boolintfloatdouble,所以这很有效。我什至没有考虑过使用继承。
【解决方案2】:

处理类和非类类型的方法,感谢 SFINAE:

template<typename T, typename Enabler = void> class TWrapper;

template<typename T>
class TWrapper<T, std::enable_if_t<std::is_class<T>::value>> : public T {
public:
    TWrapper()=delete;

    using T::T;
};

template<typename T>
class TWrapper<T, std::enable_if_t<!std::is_class<T>::value>>
{
public:
    TWrapper()=delete;

    T value;
    TWrapper(T arg) : value(arg) {}
    operator T() const { return value; }
};

Demo

【讨论】:

    猜你喜欢
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 2016-09-05
    • 2013-12-12
    相关资源
    最近更新 更多