Что не так с моим SFINAE ?: Тестирование поддерживаемых операторов - PullRequest
0 голосов
/ 11 июня 2019

Код, который имеет проблему:

template <typename=std::enable_if_t<supports_v<std::equal_to<>, T>> >
bool alreadyValue(const T &value) { return this->value == value; }
// alternate case if T does not support equals operator
bool alreadyValue(const T &value) { return false; }

Вот мои определения поддержки:

template<typename F, typename... T, typename = decltype(std::declval<F>()(std::declval<T>()...))>
std::true_type  supports_test(const F&, const T&...);
std::false_type supports_test(...);

template<typename> struct supports;
template<typename F, typename... T> struct supports<F(T...)>
    : decltype(supports_test(std::declval<F>(), std::declval<T>()...)){};

template<typename F, typename T>
constexpr bool supports_v = supports<F(T, T)>::value;

template<typename F, typename... T>
constexpr bool all_supports_v = (supports<F(T, T)>::value && ...);

Теперь MSVC 19.20 не имеет проблем с этим кодом.

Но GCC 9.1 жалуется, что:

Вместо 'шаблонаиспользуя enable_if_t = typename std :: enable_if :: type [with bool _Cond = support_v;_Tp = void] ':

ошибка : нет типа с именем' type 'в' struct std :: enable_if'

Так как SFINAE знает, что " no type in struct " должна молча завершиться сбоем, поскольку это не ошибка, мой вопрос, сделал ли я что-то не так?

Вот пример того, с чем я работаю:

1 Ответ

0 голосов
/ 12 июня 2019

Как указано @ rubenvb и @ Mike Spencer , enable_if не находится в неоцененном контексте, поскольку универсальный тип не зависит от функции. Так что нет СФИНАЕ.

В качестве решения я вместо этого построил функцию как общую вспомогательную функцию:

template<typename T, bool=supports_v<std::equal_to<>, T>>
struct is_equal_t;
template<typename T>
struct is_equal_t<T, true> {
    bool operator() (const T& x, const T& y) const { return x==y; }
};
template<typename T>
struct is_equal_t<T, false> {
    bool operator() (const T& x, const T& y) const { return false; }
};

template<typename T>
bool is_equal(const T& x, const T& y) {
    static is_equal_t<T> cmp;
    return cmp(x, y);
}
...