c++ - 可变参数构造函数中的 SFINAE

标签 c++ templates constructor variadic-templates c++17

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

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 )。虽然这会产生 std::false_type对于 T , 它会导致 std::true_type对于 StrongAlias<T> ,这可能意味着 StrongAlias<T> 的不必要的编译错误T 不存在.

最佳答案

只需将 std::enable_if_t 更改为非类型模板参数:

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)...) {}
};

关于c++ - 可变参数构造函数中的 SFINAE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49372964/

相关文章:

c++ - 构造函数中的虚方法

C# Struct 没有无参数构造函数?看看我需要完成什么

c# - 抽象类的 protected 与公共(public)构造函数?有区别吗?

c++ - 模板函数的简单脚本引擎模板数据类型

c++ - 如何在不丢失原始调用堆栈的情况下重新抛出异常?

c++ - C++调用抽象基类的构造函数

wordpress - 更新后 WP-Admin 中的 Javascript 失败

c++ - 类模板友好函数模板

c++ - 是否可以重新启动 boost::future?

c++ - 模板类中引用的引用类型是什么