Создание нескольких реализаций классов на основе параметра шаблона - PullRequest
3 голосов
/ 17 октября 2019

У меня есть шаблонный класс G:

template<int I>
class G {}

И так получилось, что мне нужно 2 реализации, основанные на этом int I

Если бы это было одно значение, я бы всегдабыть в состоянии сделать:

template<>
class G<int Specific_I>
{
    /*Implementation for that I*/
}

Если бы у меня было одно условие, которое показывает, что для реализации - 1, если оно истинно, и для реализации - 2, если ложно, я мог бы использовать совет, данный здесь


Но моя ситуация носит более общий характер.

Допустим, я определил условия для I для каждой реализации:

template<int I>
constexpr bool Condition_1 = /*whatever*/;

template<int I>
constexpr bool Condition_2 = /*whatever_v2*/;

Это позволяет легко читать и расширять при необходимости.
И если я получаю ошибку из-за отсутствия или нескольких условий, применяемых для определенного I при вызове в программе, я согласен с этим

Очевидный выбор - использовать std::enable_if_t

template<int I,
enable_if_t<Condition_1<I>>
        >
class G
{
    /*Implementation based on Condition_1*/
}

template<int I,
enable_if_t<Condition_2<I>>
        >
class G
{
    /*Implementation based on Condition_2*/
}

Но это вызывает ошибку

template parameter ‘typename std::enable_if<Condition_1<I>, void>::type <anonymous>’|

redeclared here as ‘typename std::enable_if<Condition_2<I>, void>::type <anonymous>’|

Где я допустил ошибку и как это исправить?

Ответы [ 2 ]

3 голосов
/ 17 октября 2019

Ваша ошибка в том, что вы не настроили основной шаблон для правильного использования идиомы. Если вы хотите добавить те enable_if, которые разрешают к void, первичное объявление шаблона нуждается в параметре типа в этом месте:

template<int I, typename = void>
class G; // Or static_assert in the definition. Whichever flavor you prefer.

template<int I>
class G< I, enable_if_t<Condition_1<I>> >
{
    /*Implementation based on Condition_1*/
};

template<int I>
class G< I, enable_if_t<Condition_2<I>> >
{
    /*Implementation based on Condition_2*/
};

Примечание: аргумент по умолчанию должен быть void дляваши специализации с условием соответствия. Это, конечно, приведет к ошибке, когда оба условия будут выполнены, но вы утверждаете, что с вами все в порядке, и все.

2 голосов
/ 17 октября 2019

Вам не нужно std::enable_if для этой проблемы. Поскольку ваши условия независимы, они должны инициализировать другой параметр шаблона:

template<int I, bool C1 = Condition_1<I>, bool C2 = Condition_2<I>>
struct G;

// Specializations for different conditions.
template<int I> struct G<I, false, false> { /*...*/ };
template<int I> struct G<I, false,  true> { /*...*/ };
template<int I> struct G<I,  true, false> { /*...*/ };
template<int I> struct G<I,  true,  true> { /*...*/ };

В качестве альтернативы, вы можете объединить условия в один параметр:

template<int I, unsigned C = (Condition_1<I> | Condition_2<I> * 2)>
struct G;

// Specializations for different conditions.
template<int I> struct G<I, 0> { /*...*/ };
template<int I> struct G<I, 1> { /*...*/ };
template<int I> struct G<I, 2> { /*...*/ };
template<int I> struct G<I, 3> : G<I, 2> { /*...*/ }; // Same as G<I, 2>.
...