带有外部类原型的enable_if的模板类构造函数定义

时间:2018-10-24 09:03:34

标签: c++ templates constructor enable-if

之前有一个问题与我的问题相关,该问题与模板类有关,该问题在类原型中声明的方法上使用了std::enable_if,但实际实现是在外部完成的。

来源:function implementation with enable_if outside of class definition

我想做类似的事情,但要使用类构造函数,我想用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 :(得分:0)

模板参数的默认值不应在定义中重复。例如:

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应该取决于某种推断的类型(在同一模板中)。请参阅this question。例如:

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

否则,将发生严重失败:

  

错误:“ struct std :: enable_if”中没有名为“ type”的类型

如果要为某些类型N禁用默认构造函数,则还可以在构造函数内部使用static_assert。但是,它将不是SFINAE友好的。

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>>);