【问题标题】:SFINAE: Enable class constructorSFINAE:启用类构造函数
【发布时间】:2016-08-26 08:10:13
【问题描述】:

我有一个“参数”类,它可以选择将“标识组类型”作为模板参数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,我的麻烦就来了。我的第一次尝试是在ConstrainedParameterIdentification_None 中也简单地定义IDType,但由于副作用,它不是一个解决方案。因此,我想使用IDENTIFICATION_GROUP "internals (typedefs...)" 启用/禁用参数成员方法。

所以我尝试应用 SFINAE 来启用/禁用我的构造函数(唯一关心 IDENTIFICATION_GROUP"internals 的方法):

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 ) 应该从构建中省略,对吧?那么为什么会有这样的抱怨呢?我做错了什么?

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

马丁干杯

【问题讨论】:

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


    【解决方案1】:

    我想你可以简单地用以下方式编写你的构造函数

    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)
    { /* ... */ }
    

    【讨论】:

    • 因此,将不存在的类型作为模板参数传递仍然是 SFINAE 的有效案例。很高兴知道!
    【解决方案2】:

    问题是您试图将不存在的类型传递给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() { }
    
    };
    

    SFINAE 需要虚拟Unused 模板参数才能工作(相关方法必须至少依赖于一个模板参数)。

    【讨论】:

      猜你喜欢
      • 2018-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      相关资源
      最近更新 更多