c++ - 在启用基于它的构造函数时是否总是需要复制类模板参数?

标签 c++ templates c++11 language-lawyer sfinae

一般在使用基于类模板类型的enable_if时,需要复制类模板类型作为构造函数或方法的模板参数:

template <
    typename U = T,
    typename = typename std::enable_if<
        !std::is_void<U>::value
    >::type
>
Class() { }

究竟什么时候需要(或不需要)?

例如,下面的代码可以在 G++、Clang 和 VC++ 上正常编译...

template <typename T = void>
class Class {
public:
    template <
        typename U,
        typename = typename std::enable_if<
            // Is the use of T here allowed?
            std::is_void<T>::value
            || std::is_base_of<T, U>::value
        >::type
    >
    Class(U &&arg) {
        std::cout << "Derived" << std::endl;
    }

    template <
        typename U,
        typename ...U_Rest,
        typename = typename std::enable_if<
            // Is the use of T here allowed?
            !std::is_void<T>::value
            && !std::is_base_of<T, U>::value
        >::type
    >
    Class(U &&arg, U_Rest &&...rest) {
        std::cout << "Not Derived" << std::endl;
    }
};

ideone rextester

... 但直接使用 T 作为 enable_if 的一部分。具体来说,如果 Tvoid,构造函数的“派生”版本将始终启用,而“非派生”版本将始终禁用,无论参数 U

根据标准,上述实际上合法吗?或者编译器只是接受它,可能是因为“不需要诊断”?

最佳答案

SFINAE适用于模板方法,应该不是hard failure(所以主要应该看它的模板参数)

这里你的条件取决于U,所以没问题。

注意你应该更喜欢

template <typename U, std::enable_if_t<cond>* = nullptr>

结束

template <typename U, typename = std::enable_if_t<cond>>

允许写入禁用版本

template <typename U, std::enable_if_t<!cond>* = nullptr>

作为

template <typename U, typename = std::enable_if_t<cond>> //...
template <typename U, typename = std::enable_if_t<!cond>> // ...

具有相同的签名。

关于c++ - 在启用基于它的构造函数时是否总是需要复制类模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39100394/

相关文章:

c++ - 在 C++ 中将输出定向到 .txt 文件

c++ - 一个类可以有将当前类作为参数的成员吗

c++ - 类内枚举前向声明是否可能?

c++ - linux 中可执行文件的主管

c++ - std::declval<T>()、SFINAE 和删除的构造函数

c++ - 在具有继承的模板链表中重载 << 运算符

php - 网站多页 |模板 |搜索

c++ - 对象销毁时调用回调函数

c++ - 无锁代码中的延迟初始化

c++ - 编写元组的C++映射并设置为文件