Search code examples
c++c++11constructorsfinaeenable-if

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


Solution

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