【问题标题】:SFINAE Constructors [duplicate]SFINAE 构造函数 [重复]
【发布时间】:2018-07-11 19:04:28
【问题描述】:

我一直喜欢这样的 SFINAE 函数语法,似乎一般都很好用!

template <class Integer, class = typename std::enable_if<std::is_integral<Integer>::value>::type>
T(Integer n) {
    // ...
}

但是当我想在同一个班级这样做时遇到了一个问题......

template <class Float, class = typename std::enable_if<std::is_floating_point<Float>::value>::type>
T(Float n) {
    // ...
}

遇到这样的错误:

./../T.h:286:2: error: constructor cannot be redeclared
        T(Float n) {
        ^
./../T.h:281:2: note: previous definition is here
        T(Integer n) {
        ^
1 error generated.

这些构造函数不应该只存在于适当的类型中,并且不能同时存在吗?为什么会发生冲突?

我是不是有点厚脸皮了?

另一方面,这确实有效(但我不太喜欢这种语法):

template <class Integer>
T(Integer n, typename std::enable_if<std::is_integral<Integer>::value>::type* = nullptr) {
}

template <class Float>
T(Float n, typename std::enable_if<std::is_floating_point<Float>::value>::type* = nullptr) {
}

【问题讨论】:

    标签: c++ sfinae


    【解决方案1】:

    改用非类型模板参数:

    template <class Integer,
        std::enable_if_t<std::is_integral<Integer>::value, int> = 0>
    T(Integer n) {
        // ...
    }
    
    template <class Float,
        std::enable_if_t<std::is_floating_point<Float>::value, int> = 0>
    T(Float n) {
        // ...
    }
    

    这是可行的,因为编译器必须先替换第一个模板参数,然后才能确定值参数的类型。

    【讨论】:

    • 我不能说我理解为什么基于值的事情会完成 SFINAE 而基于类型名的事情却没有......你能再解释一下吗?那么是不是可以说基于 value 的 SFINAE 比基于 typename 的 SFINAE 更“强”呢?
    【解决方案2】:

    解决此问题的一种方法是添加额外的, typename=void 参数,以便所有重载都没有相同数量的模板参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多