SFINAE не работает :(

223
04 мая 2017, 15:33

Почему не компилируется?

template <size_t x, typename value_type>
class A {
    std::enable_if_t<x == 1, value_type> operator()() { return 1; }
    std::enable_if_t<x != 1, value_type> operator()() { return 2; }
};
Answer 1

SFINAE работает на уровне выведения аргументов шаблона функции, но Ваши функции (операторы) не являются шаблонными, поэтому разговора о SFINAE быть не может в принципе — ему тут неоткуда взяться. При любых раскладах у Вас в классе всегда будут 2 функции, одна из которых может быть валидна, а вторая, на контрасте с первой, будет невалидной.

Но это если мы сделаем обе функции шаблонными, добавив некий фиктивный параметр шаблона. В текущей же редакции код просто-напросто невалиден в любом случае в силу того, что перегрузка нешаблонных функций по возвращаемому значению невозможна т.к. возвращаемый тип не является частью сигнатуры оной.

Answer 2

SFINAE работает только для шаблонов (когда есть template непосредственно для сущности, для которой применяется SFINAE). Попробуйте так:

template <size_t x, typename value_type>
class A {
   template<class Enable = std::enable_if_t<x == 1>>
   value_type operator()() { return 1; }
   template<class Enable = std::enable_if_t<x != 1>>
   value_type operator()() { return 2; }
};

Еще вариант, можно использовать частичную специализацию шаблона для класса

template <size_t x, typename value_type>
class A {
   value_type operator()() { return 2; }
};
template <typename value_type>
class A <1, value_type> {
   value_type operator()() { return 1; }
};
Answer 3

Компилятор запрещает перегрузки с одинаковыми прототипами несмотря на SFINAE. Так что используйте вместо него обычное условие внутри функции.

template <size_t x, typename value_type>
class A {
    value_type operator()() {
        return (x == 1) ? 1 : 2;
    }
};

Любой более-менее современный компилятор оптимизирует условия с участием констант (к которым относится и шаблонный параметр x).

Answer 4

В 17 стандарте появится compile time if - именно то, что нужно в этой ситуации :)

READ ALSO
Как пользоваться QJsonDocument

Как пользоваться QJsonDocument

Подскажите пожалуйста как пользоваться QJsonDocumentЯ cделал запрос на сервер

463
C++ Парсинг строки

C++ Парсинг строки

Привет всемЕсть строка с аргументами к примеру "Привет, меня зовут %1, мне %2 лет

418
Игнорирование delete для указателя на объект в статической памяти

Игнорирование delete для указателя на объект в статической памяти

"Использование оператора delete на указателе на объект, который не был создан при помощи оператора new, создает непрогнозируемый результат" (сайт...

263
OpenGl и ввод значений

OpenGl и ввод значений

Здравствуйте, помогите пожалуйста

332