启用类构造函数

SFINAE: Enable class constructor

本文关键字:构造函数 启用      更新时间:2023-10-16

我有一个"parameter"类,可选地持有一个"识别组类型"作为模板参数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类时,使用如下所示的类类型(有趣的部分是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 )应该从构建中省略,对吗?那么为什么会有这样的抱怨呢?我做错了什么?

提前感谢任何愿意帮助…

欢呼马丁

我认为您可以简单地按照以下方式编写构造函数

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和恼人的::type,所以

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

问题是您试图将不存在的类型传递给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工作所必需的(所讨论的方法必须依赖于至少一个模板参数)。