Martin Kopecký Martin Kopecký - 2 months ago 17
C++ Question

SFINAE: Enable class constructor

I have a "parameter" class which optionally holds an "identification group type" as template argument

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


While instantinating the Parameter class, a type of class like listed below is used (interresting part is
using IDType = int;
):

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


Unless I instantiante the parameter like this:

Parameter<si::length, double, SampleIdentificationGroup> Param;


everything is working fine.

But once I wanna use the default value of
IDENTIFICATION_GROUP
-
ConstrainedParameterIdentification_None
, there comes my trouble. My first attempt was to simply define
IDType
also in
ConstrainedParameterIdentification_None
but due to side effects it is not a solution. Therefore I would like to enable/disable parameter member methods using the
IDENTIFICATION_GROUP
"internals (typedefs...)".

So I tried to apply SFINAE to enable/disable my constructor (the only method taking care about
IDENTIFICATION_GROUP
"internals):

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


In human language what I am trying to reach is "If
IDENTIFICATION_GROUP
is
ConstrainedParameterIdentification_None
, exclude the whole method.".

But GCC complains about the type IDType not being defined:

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


But due to SFINAE, the
Parameter( const typename IDENTIFICATION_GROUP::IDType ID )
should be omitted from build, right? So why such a complains? What am I doing wrong?

Many thanks in advance to anyone willing to help...

Cheers Martin

Answer

I suppose you could simply write your constructor in the following way

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

If you can use C++14, std::enable_it_t should avoid an annoing typename and an annoing ::type, so

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