SFINAE在可变构造函数中 [英] SFINAE in variadic constructor

查看:56
本文介绍了SFINAE在可变构造函数中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想定义一个通用的强别名类型,即类型

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> 对于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆