SFINAE在可变构造函数中 [英] SFINAE in variadic constructor
问题描述
我想定义一个通用的强别名类型,即类型
I want to define a generic strong alias type, i.e. a type
template<typename T, auto ID = 0>
class StrongAlias {
T value;
};
对于类型 T
a StrongAlias< T>
的使用方式与 T
完全相同,但 StrongAlias< T ,0>
和 StrongAlias< T,1>
是不同的类型,不能有效地相互转换。
为了尽可能完美地模仿 T
,我希望我的 StrongAlias
具有相同的构造函数为 T
。
这意味着我想执行以下操作:
such that for a type T
a StrongAlias<T>
can be used in exactly the same way as T
, but StrongAlias<T, 0>
and StrongAlias<T, 1>
are different types that can not be implecitly converted to each other.
In order to mimic a T
as perfectly as possible, I would like my StrongAlias
to have the same constructors as T
.
This means I would like to do something like the following:
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参数包必须是最后一个模板参数
,就像clang 5.0会告诉我的那样。
我想到的另一种使用SFINAE的方法是在返回类型中,但是由于构造函数没有返回类型,因此这似乎也不起作用。
except that this wouldn't work since the template parameter pack must be the last template parameter
, as clang 5.0 would tell me.
The other way to use SFINAE that I thought of would be in the return type, but since a constructor doesn't have a return type, this does not seem to work either.
是否可以在构造函数中的可变参数模板参数包上使用SFINAE?
Is there any way to use SFINAE on a variadic template parameter pack in a constructor?
或者,如果没有,我可以完成我想用另一种方式吗?
Alternatively, if there isn't one, can I accomplish what I want in another way?
请注意,对于我来说,从 T
隐式构造是不够的,例如 StrongAlias< std :: optional< int>>
的示例显示:如果 StrongAlias
只能隐式从 std :: optional< int>
构造,则不能从 std :: nullopt
(键入 std :: nullopt_t
),因为这将涉及2个用户定义的转换。我真的很想拥有别名类型的所有构造函数。
Note that being implicitly constructible from a T
isn't enough in my case, as the example of StrongAlias<std::optional<int>>
shows: If StrongAlias
can only be implictly constructed from a std::optional<int>
, it cannot be be constructed from a std::nullopt
(of type std::nullopt_t
), because that would involve 2 user-defined conversions. I really want to have all constructors of the aliased type.
编辑:
当然,没有SFINAE也可以实现此功能,并使程序无效如果 StrongAlias
是根据不兼容的参数构造的。但是,虽然这在我的特定情况下是可以接受的行为,但显然不是最佳选择,因为 StrongAlias
可以在模板中使用,该模板查询给定类型是否可从一些参数(通过 std :: is_constructible
)。虽然这会为 T
生成 std :: false_type
,但会导致 std ::
StrongAlias< T>
,这可能意味着 StrongAlias< T> $ c的不必要的编译错误$ c>对于
T
而言是不存在的。
Of course it would be possible to implement this without SFINAE and let the program be invalid if a StrongAlias
is constructed from incompatible arguments. However, while this would be an acceptable behaviour in my specific case, it is clearly not optimal as the StrongAlias
may be used in a template that queries if the given type is constructible from some arguments (via std::is_constructible
). While this would yield a std::false_type
for T
, it would result in a std::true_type
for StrongAlias<T>
, which could mean unnecessary compile errors for StrongAlias<T>
that wouldn't exist for T
.
推荐答案
将 std :: enable_if_t
更改为非类型模板参数:
Just change std::enable_if_t
to a non-type template parameter:
template<typename T, auto ID = 0>
class StrongAlias {
T value;
public:
template<typename... Args, std::enable_if_t<std::is_constructible_v<T, Args...>, int> = 0>
StrongAlias(Args&&... args) noexcept(noexcept(T(std::declval<Args>()...)))
: value(std::forward<Args>(args)...) {}
};
这篇关于SFINAE在可变构造函数中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!