SFINAE:启用类构造函数

时间:2016-08-26 08:10:14

标签: c++ c++11 constructor sfinae enable-if

我有一个“参数”类,可选择将“标识组类型”作为模板参数typename IDENTIFICATION_GROUP保存:

struct ConstrainedParameterIdentification_None {};

template<typename UNIT_TYPE, typename DATA_TYPE = double, typename IDENTIFICATION_GROUP = ConstrainedParameterIdentification_None>
class Parameter
{
    /* Constructor - the only method taking care about valid IDENTIFICATION_GROUP */
    template<typename = std::enable_if<!std::is_same<IDENTIFICATION_GROUP, ConstrainedParameterIdentification_None>::value>>
    Parameter( const typename IDENTIFICATION_GROUP::IDType ID )
    { /* ... */ }
};

在使用Parameter类时,会使用下面列出的类型(interresting part为using IDType = int;):

struct SampleIdentificationGroup
{
    using IDType = int;
    /* ... */
};

除非我像这样实例化参数:

Parameter<si::length, double, SampleIdentificationGroup> Param;
一切都运转良好。

但是,一旦我想使用默认值IDENTIFICATION_GROUP - ConstrainedParameterIdentification_None,就会遇到麻烦。我的第一次尝试是简单地在IDType中定义ConstrainedParameterIdentification_None,但由于副作用,它不是解决方案。因此,我想使用IDENTIFICATION_GROUP“internals(typedefs ...)”启用/禁用参数成员方法。

所以我尝试应用SFINAE来启用/禁用我的构造函数(唯一关注IDENTIFICATION_GROUP“内部构件的方法):

template<typename = std::enable_if<!std::is_same<IDENTIFICATION_GROUP, ConstrainedParameterIdentification_None>::value>>
Parameter( const typename IDENTIFICATION_GROUP::IDType ID )
{ /* ... */ }

在人类语言中,我想要触及的是“如果 IDENTIFICATION_GROUP ConstrainedParameterIdentification_None ,请排除整个方法。< /强>”。

但是GCC抱怨没有定义类型IDType:

error: no type named ‘IDType’ in ‘struct Base::ConstrainedParameterIdentification_None’
   Parameter( const typename IDENTIFICATION_GROUP::IDType ID )

但由于SFINAE,构建中应省略Parameter( const typename IDENTIFICATION_GROUP::IDType ID ),对吧?那么为什么这么抱怨呢?我做错了什么?

非常感谢任何愿意帮助的人......

干杯马丁

2 个答案:

答案 0 :(得分:2)

我想您可以按照以下方式编写构造函数

template <typename IG = IDENTIFICATION_GROUP>
   Parameter (typename std::enable_if<false == std::is_same<IG, ConstrainedParameterIdentification_None>::value, typename IG::IDType>::type const ID)
{ /* ... */ }

如果你可以使用C ++ 14,那么std::enable_it_t应该避免一个令人讨厌的typename和一个annoing ::type,所以

template <typename IG = IDENTIFICATION_GROUP>
   Parameter (std::enable_if_t<false == std::is_same<IG, ConstrainedParameterIdentification_None>::value, typename IG::IDType> const ID)
{ /* ... */ }

答案 1 :(得分:1)

问题在于您尝试将不存在的类型传递给std::enable_if。要解决这个问题,您可以轻松地提出自己的enable_if版本:

template <typename IDENTIFICATION_GROUP = ConstrainedParameterIdentification_None> struct my_enable_if {
    using type = typename IDENTIFICATION_GROUP::IDType;
};
template <> struct my_enable_if<ConstrainedParameterIdentification_None> {

};

template<typename IDENTIFICATION_GROUP = ConstrainedParameterIdentification_None> class Parameter {
    public:
        template <typename Unused = IDENTIFICATION_GROUP>
        Parameter(typename my_enable_if<Unused>::type ID) { }
        Parameter() { }

};

虚拟Unused模板参数是SFINAE工作所必需的(有问题的方法必须至少依赖于一个模板参数)。