Подтвердить что ты не робот

Выберите конструктор классов с помощью enable_if

Рассмотрим следующий код:

#include <iostream>
#include <type_traits>

template <typename T>
struct A {
    int val = 0;

    template <class = typename std::enable_if<T::value>::type>
    A(int n) : val(n) {};
    A(...) { }

    /* ... */
};

struct YES { constexpr static bool value = true; };
struct NO { constexpr static bool value = false; };

int main() {
    A<YES> y(10);
    A<NO> n;
    std::cout << "YES: " << y.val << std::endl
              << "NO:  " << n.val << std::endl;
}

Я хочу выборочно определить конструктор A:: A (int) только для некоторых типов, используя enable_if. Для всех других типов существует конструктор по умолчанию A:: A (...), который должен быть случайным по умолчанию для компилятора при неудачной замене. Однако это имеет смысл для меня, компилятор (gcc version 4.9.0 20130714) все еще жалуется

sfinae.cpp: При создании "структуры А": sfinae.cpp: 19: 11:
требуется отсюда sfinae.cpp: 9: 5: ошибка: нет типа с именем "тип" в
'struct std:: enable_if'
     A (int n): val (n) {};

Что-то вроде этого возможно для конструктора? Возможно ли это с другим конструктором (конструкторами) (copy-constructor и move-constructor)?

4b9b3361

Ответ 1

Я думаю, что это не может работать с одним параметром шаблона по умолчанию, потому что его значение необходимо разрешить при создании экземпляра класса.

Нам нужно отложить подстановку до момента создания экземпляра конструктора. Один из способов заключается в том, чтобы по умолчанию задать параметр шаблона в T и добавить конструктору дополнительный дополнительный параметр:

template<typename U = T>
A(int n, typename std::enable_if<U::value>::type* = 0) : val(n) { }

Ответ 2

Обычно это делается с использованием анонимного аргумента по умолчанию:

A(int n, typename std::enable_if<T::value>::type* = 0) : val(n) {};

Забастовкa >

Вы не можете использовать параметры шаблона из класса в методы вывода SFINAE. SO одним способом является добавление фиктивного типа, заменяющего int:

см. http://ideone.com/2Gnyzj

#include <iostream>
#include <type_traits>

template <typename T>
struct A {
    int val = 0;

    template<typename Integer
            ,typename  = typename std::enable_if<T::value && sizeof(Integer)>::type
            >
    A(Integer n) : val(n) {};

    A(...) {}
    /* ... */
};

struct YES { constexpr static bool value = true; };
struct NO { constexpr static bool value = false; };

int main() {
    A<YES> y(10);
    A<NO> n;
    std::cout << "YES: " << y.val << std::endl
              << "NO:  " << n.val << std::endl;
}

Это работает, потому что вы используете параметр шаблона члена для SFINAE из конструктора, но тест всегда прав, поэтому он не загрязняет ваши проверки.