我想定义一个通用的强别名类型,即一个类型
template<typename T, auto ID = 0>
class StrongAlias {
T value;
};
这样对于一个类型T
a StrongAlias<T>
可以以完全相同的方式使用T
, but StrongAlias<T, 0>
and StrongAlias<T, 1>
是不同的类型,不能相互隐式转换。
为了模仿一个T
尽可能完美,我希望我的StrongAlias
具有相同的构造函数T
。
这意味着我想做类似以下的事情:
template<typename T, auto ID = 0>
class StrongAlias {
T value;
public:
// doesn't work
template<typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
StrongAlias(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
: value(std::forward<Args>(args)...) {}
};
除了这行不通,因为template parameter pack must be the last template parameter
,正如 clang 5.0 会告诉我的那样。
我想到的使用 SFINAE 的另一种方法是返回类型,但由于构造函数没有返回类型,因此这似乎也不起作用。
有没有办法在构造函数中的可变模板参数包上使用 SFINAE?
或者,如果没有,我可以用另一种方式完成我想要的事情吗?
请注意,可以从 a 隐式构造T
就我而言还不够,例如StrongAlias<std::optional<int>>
显示:如果StrongAlias
只能从隐式构造std::optional<int>
,它不能由std::nullopt
(类型std::nullopt_t
),因为这将涉及 2 个用户定义的转换。我真的想要拥有别名类型的所有构造函数。
编辑:
当然,可以在没有 SFINAE 的情况下实现这一点,并在以下情况下让程序无效:StrongAlias
是由不兼容的参数构造的。然而,虽然在我的具体情况下这是可以接受的行为,但它显然不是最佳的,因为StrongAlias
可以在模板中使用,该模板查询给定类型是否可以从某些参数构造(通过std::is_constructible
)。虽然这会产生std::false_type
for T
,这会导致std::true_type
for StrongAlias<T>
,这可能意味着不必要的编译错误StrongAlias<T>
那不会存在T
.