使用指定初始化程序时,我可以强制用户为成员提供值吗?
Can I force a user to provide a value for a member when using designated initializers?
我创建了一个选项结构,旨在通过指定的初始化程序使用:
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>
,但没有默认初始化程序。
您澄清说这是关于任意 类,而不是原始类型。对于任意 类,具有任意构造函数:只需删除构造函数,但显式 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
即可。没有那么多原始类型需要处理。
处理 类 和非 类 类型的方法,感谢 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; }
};
我创建了一个选项结构,旨在通过指定的初始化程序使用:
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>
,但没有默认初始化程序。
您澄清说这是关于任意 类,而不是原始类型。对于任意 类,具有任意构造函数:只需删除构造函数,但显式 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
即可。没有那么多原始类型需要处理。
处理 类 和非 类 类型的方法,感谢 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; }
};