Как включить enable_if в класс с аргументами вариационного шаблона?
Предположим, что у меня есть класс со следующей сигнатурой:
template <typename T, typename... Args>
class A;
Но как ведет себя этот класс, он должен зависеть от некоторого другого параметра, скажем, это значение 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; }
Однако эта программа дает следующую ошибку:
prog.cpp: 6: 11: ошибка: пакет параметров 'Арги должны быть в конце список параметров шаблона класс A;
Я изо всех сил пытался найти хороший источник информации об использовании enable_if
для выбора классов с вариационными шаблонами. Единственный вопрос, который я смог найти, это:
Как использовать std:: enable_if с вариационным шаблоном
Но, несмотря на название, этот вопрос и его ответы не очень помогают. Если кто-то может предоставить или связать руководство о том, как к этому нужно подходить, и почему это будет оценено.
Ответы
Ответ 1
Прежде всего, вы пытаетесь написать несколько определений шаблона класса. Это не допускается, поскольку оно нарушает одно правило определения. Если вы хотите сделать условное включение с помощью классов, вам нужны специализации. Кроме того, сообщение об ошибке компилятора уже говорило вам, что вы не можете иметь пакет переменных параметров в середине списка параметров.
Один из способов сделать это:
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...> {};
Jonathan way также отлично подходит, если условие действительно является bool
, но это может быть не полезно, если вы хотите добавить больше специализаций, каждый из которых зависит от несколько условий.
Ответ 2
Похоже, что для ваших целей вам не нужно включать/отключать класс, вам просто нужна частичная специализация:
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...>;