SFINAE:启用 class 构造函数
SFINAE: Enable class constructor
我有一个 "parameter" class 可以选择将 "identification group type" 作为模板参数 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 )
{ /* ... */ }
};
在实例化参数 class 时,使用了如下所列的 class 类型(有趣的部分是 using IDType = int;
):
struct SampleIdentificationGroup
{
using IDType = int;
/* ... */
};
除非我像这样实例化参数:
Parameter<si::length, double, SampleIdentificationGroup> Param;
一切正常。
但是一旦我想使用默认值IDENTIFICATION_GROUP
- ConstrainedParameterIdentification_None
,我的麻烦就来了。我的第一次尝试是在 ConstrainedParameterIdentification_None
中也简单地定义 IDType
但由于副作用,它不是解决方案。因此我想 enable/disable 参数成员方法使用 IDENTIFICATION_GROUP
"internals (typedefs...)".
所以我尝试将 SFINAE 应用于 enable/disable 我的构造函数(唯一关注 IDENTIFICATION_GROUP
“内部”的方法):
template<typename = std::enable_if<!std::is_same<IDENTIFICATION_GROUP, ConstrainedParameterIdentification_None>::value>>
Parameter( const typename IDENTIFICATION_GROUP::IDType ID )
{ /* ... */ }
在人类语言中,我试图达到的是“If IDENTIFICATION_GROUP
is 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 )
应该从构建中省略,对吧?那么为什么会有这样的抱怨呢?我做错了什么?
非常感谢任何愿意提供帮助的人...
干杯马丁
问题是您试图将不存在的类型传递给 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
模板参数才能工作(相关方法必须至少依赖于一个模板参数)。
我想您可以按以下方式简单地编写构造函数
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)
{ /* ... */ }
我有一个 "parameter" class 可以选择将 "identification group type" 作为模板参数 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 )
{ /* ... */ }
};
在实例化参数 class 时,使用了如下所列的 class 类型(有趣的部分是 using IDType = int;
):
struct SampleIdentificationGroup
{
using IDType = int;
/* ... */
};
除非我像这样实例化参数:
Parameter<si::length, double, SampleIdentificationGroup> Param;
一切正常。
但是一旦我想使用默认值IDENTIFICATION_GROUP
- ConstrainedParameterIdentification_None
,我的麻烦就来了。我的第一次尝试是在 ConstrainedParameterIdentification_None
中也简单地定义 IDType
但由于副作用,它不是解决方案。因此我想 enable/disable 参数成员方法使用 IDENTIFICATION_GROUP
"internals (typedefs...)".
所以我尝试将 SFINAE 应用于 enable/disable 我的构造函数(唯一关注 IDENTIFICATION_GROUP
“内部”的方法):
template<typename = std::enable_if<!std::is_same<IDENTIFICATION_GROUP, ConstrainedParameterIdentification_None>::value>>
Parameter( const typename IDENTIFICATION_GROUP::IDType ID )
{ /* ... */ }
在人类语言中,我试图达到的是“If IDENTIFICATION_GROUP
is 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 )
应该从构建中省略,对吧?那么为什么会有这样的抱怨呢?我做错了什么?
非常感谢任何愿意提供帮助的人...
干杯马丁
问题是您试图将不存在的类型传递给 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
模板参数才能工作(相关方法必须至少依赖于一个模板参数)。
我想您可以按以下方式简单地编写构造函数
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)
{ /* ... */ }