2016-08-26 3 views
3

У меня есть класс «параметра», который необязательно имеет место в «групповой идентификации типа» в качестве аргумента шаблона typename IDENTIFICATION_GROUP:SFINAE: Включить конструктор класса

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

В то время как instantinating класса параметров, типа класса, как перечисленные ниже является б (interresting часть using IDType = int;):

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

Если я не instantiante параметр так:

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

все работает нормально.

Но как только я хочу использовать значение по умолчанию IDENTIFICATION_GROUP - ConstrainedParameterIdentification_None, наступает моя проблема. Моя первая попытка состояла в том, чтобы просто определить IDType также в ConstrainedParameterIdentification_None, но из-за побочных эффектов это не решение. Поэтому я хотел бы включить/отключить методы-члены параметра, используя «внутренности (typedefs ...)» IDENTIFICATION_GROUP ».

Так что я попытался применить 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) должны быть исключены из сборки, правда Так почему такое жалуется Что я делаю? неправильно?

Большое спасибо заранее, кто готов помочь ...

Приветствия Martin

ответ

2

Я полагаю, вы могли бы просто написать конструктор следующим образом

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 должны избежать annoing typename и annoing ::type, так

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

Таким образом, передача несуществующего типа в качестве параметра шаблона по-прежнему является действительным случаем для SFINAE. Хорошо знать! – Dmitry

1

проблема заключается в тха t вы пытаетесь передать несуществующий тип на 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 работы (метод вопрос должен зависеть, по меньшей мере, одного параметра шаблона).

Смежные вопросы