Как включить enable_if в класс с аргументами вариационного шаблона?

Предположим, что у меня есть класс со следующей сигнатурой:

template <typename t,="" typename...="" args="">
class A;
</typename>

Но как ведет себя этот класс, он должен зависеть от некоторого другого параметра, скажем, это значение T::value:

template <typename t,="" typename...="" args,="" typename="" enable="">
class A;
template <typename t,="" typename...="" args,="" typename="typename" std::enable_if<t::value="">::type>
class A
{
 // do something
};
template <typename t,="" typename...="" args,="" typename="typename" std::enable_if<!t::value="">::type>
class A
{
 // do something else
};
int main() { return 0; }
</typename></typename></typename>

Однако эта программа дает следующую ошибку:

prog.cpp: 6: 11: ошибка: пакет параметров 'Арги должны быть в конце список параметров шаблона      класс A;

Я изо всех сил пытался найти хороший источник информации об использовании enable_if для выбора классов с вариационными шаблонами. Единственный вопрос, который я смог найти, это:

Как использовать std:: enable_if с вариационным шаблоном

Но, несмотря на название, этот вопрос и его ответы не очень помогают. Если кто-то может предоставить или связать руководство о том, как к этому нужно подходить, и почему это будет оценено.

2 ответа

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

Один из способов сделать это:

namespace detail {
template<typename t,="" typename="" enable,="" typename...="" args="">
class A_impl;
template<typename t,="" typename...="" args="">
class A_impl<t, typename="" std::enable_if<t::value="">::type, Args...> {
 // code here
};
template<typename t,="" typename...="" args="">
class A_impl<t, typename="" std::enable_if<!t::value="">::type, Args...> {
 // code here
};
}
template<typename t,="" typename...args="">
class A : public detail::A_impl<t, void,="" args...=""> {};
</t,></typename></t,></typename></t,></typename></typename>

Jonathan way также отлично подходит, если условие действительно является bool, но это может быть не полезно, если вы хотите добавить больше специализаций, каждый из которых зависит от несколько условий.


Похоже, что для ваших целей вам не нужно включать/отключать класс, вам просто нужна частичная специализация:

template <typename t,="" bool="" b="T::value," typename...="" args="">
 class A;
template <typename t,="" typename...="" args="">
 class A<t, true,="" args...="">;
template <typename t,="" typename...="" args="">
 class A<t, false,="" args...="">;
</t,></typename></t,></typename></typename>

licensed under cc by-sa 3.0 with attribution.