Может ли SFINAE предотвратить неоднозначные перегрузки операторов? - PullRequest
2 голосов
/ 26 января 2020

Я думал, что следующий код скомпилируется, потому что конфликтующие перегрузки удалены. Но компилятор (G CC) говорит: 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(){}

1 Ответ

2 голосов
/ 26 января 2020

С ссылка для 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
};
...