首页 > 解决方案 > SFINAE 不能防止模棱两可的运算符重载吗?

问题描述

我认为下面的代码可以编译,因为冲突的重载被 SFINAE 消除了。但是编译器(GCC)说:void Foo<X>::bar(Xd) const' cannot be overloaded. 有没有一种简单的方法来解决它,还是我必须专门研究整个问题Foo

#include <type_traits>

struct A{};

template<typename X>
struct Foo {
    template<typename Xd=X, typename = std::enable_if_t<std::is_arithmetic<Xd>::value>>
    void bar() const {
    }

    template<typename Xd=X, typename = std::enable_if_t<std::is_same<Xd,A>::value>>
    void bar() const {
    }
};

int main(){}

标签: c++compiler-errorsoperator-overloadingc++14sfinae

解决方案


来自std::enable_if的参考

一个常见的错误是声明两个仅在默认模板参数上有所不同的函数模板。这不起作用,因为声明被视为同一函数模板的重新声明(默认模板参数不计入函数模板等效项)。

/*** WRONG ***/
struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              typename = std::enable_if_t<std::is_integral<Integer>::value>
    >
    T(Integer) : m_type(int_t) {}

    template <typename Floating,
              typename = std::enable_if_t<std::is_floating_point<Floating>::value>
    >
    T(Floating) : m_type(float_t) {} // error: treated as redefinition
};


/* RIGHT */   
struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              std::enable_if_t<std::is_integral<Integer>::value, int> = 0
    >
    T(Integer) : m_type(int_t) {}

    template <typename Floating,
              std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
    >
    T(Floating) : m_type(float_t) {} // OK
};

推荐阅读