代码之家  ›  专栏  ›  技术社区  ›  Evan Teran

sfinae构造函数[副本]

  •  4
  • Evan Teran  · 技术社区  · 7 年前

    我一直喜欢这样的函数的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) {
    }
    
    2 回复  |  直到 7 年前
        1
  •  8
  •   Justin    7 年前

    请改用非类型模板参数:

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

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

        2
  •  1
  •   o11c    7 年前

    解决这个问题的方法之一是增加 , typename=void 使所有重载都不具有相同数量的模板参数。