【发布时间】:2018-08-28 14:28:44
【问题描述】:
我想定义一个通用的强别名类型,即一个类型
template<typename T, auto ID = 0>
class StrongAlias {
T value;
};
这样对于类型T 和StrongAlias<T> 可以以与T 完全相同的方式使用,但StrongAlias<T, 0> 和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?
或者,如果没有,我可以用另一种方式完成我想要的吗?
请注意,在我的情况下,从 T 隐式构造是不够的,正如 StrongAlias<std::optional<int>> 的示例所示:如果 StrongAlias 只能从 std::optional<int> 隐式构造,则无法构造来自std::nullopt(std::nullopt_t 类型),因为这将涉及 2 个用户定义的转换。我真的很想拥有别名类型的所有构造函数。
编辑:
当然,可以在没有 SFINAE 的情况下实现这一点,如果 StrongAlias 是由不兼容的参数构造的,则程序无效。然而,虽然这在我的特定情况下是可接受的行为,但它显然不是最佳的,因为StrongAlias 可以用于查询给定类型是否可以从某些参数构造的模板中(通过std::is_constructible)。虽然这会为T 生成一个std::false_type,但它会为StrongAlias<T> 生成一个std::true_type,这可能意味着StrongAlias<T> 的不必要的编译错误对于T 不存在。
【问题讨论】:
-
哪个 clang 5.0 告诉你这个?
标签: c++ templates constructor variadic-templates c++17