определение конструктора класса шаблона с enable_if вне прототипа класса - PullRequest
0 голосов
/ 24 октября 2018

Ранее был вопрос, связанный с моей проблемой, которая касалась класса шаблона, который использовал std::enable_if в методе, который объявлен в прототипе класса, но фактическая реализация выполняется за пределами.

Источник: Реализация функции с enable_if вне определения класса

Я хочу сделать нечто подобное, но с конструктором класса, который я хочу определить вне класса шаблона с метафункцией std::enable_if.

template <typename T>
using EnableIfArithmetic = typename std::enable_if<std::is_arithmetic<T>::value, void>::type;

template <typename NumericType>
class SomeClass {
public:
    // constructor definition
    template <typename = EnableIfArithmetic<NumericType>>
    SomeClass() {
        // do some stuff
    }
};

Желаемая форма:

template <typename NumericType>
class SomeClass {
public:
     // constructor declaration
     template <typename = EnableIfArithmetic<NumericType>>
     SomeClass();
};

// constructor definition
template <typename NumericType>
template <typename = EnableIfArithmetic<NumericType>>
SomeClass<NumericType>::SomeClass() {
        // constructor implementation
}

Но я не могу понять это правильно, без ошибки компиляции.Что я делаю неправильно?

1 Ответ

0 голосов
/ 24 октября 2018

Значения по умолчанию для аргументов шаблона не должны повторяться в определениях.Например:

template<typename N>
struct S {
    template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
    S(T);
};

template<typename N>
template<typename T, typename>
S<N>::S(T) { }

Неверный способ использования SFINAE: EnableIfArithmetic должен зависеть от некоторого выведенного типа (в том же шаблоне).Пожалуйста, обратитесь к этот вопрос .Например:

template<typename T = N, typename = EnableIfArithmetic<T>>
S() { }

В противном случае произойдет серьезный сбой:

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

Если вы хотите отключить конструктор по умолчанию для некоторых типов N, вы также можете использовать static_assert внутри конструктора.Тем не менее, это не будет СФИНА дружественным.

template<typename N>
struct S1 {
public:
    template<typename T = N, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
    S1() { }
};

template<typename N>
struct S2 {
public:
    S2() { static_assert(std::is_arithmetic_v<N>); }
};

static_assert(std::is_default_constructible_v<S1<int>>);
static_assert(!std::is_default_constructible_v<S1<void>>);

static_assert(std::is_default_constructible_v<S2<int>>);
static_assert(std::is_default_constructible_v<S2<void>>);
...