#c #templates #c 11 #variadic-templates
#c #шаблоны #c 11 #variadic-шаблоны
Вопрос:
У меня есть эта шаблонная функция (я помню, что где-то видел похожие вещи из SO). Это работает как с std::function
, так и std::list
с (as Container
). Но я не могу по-настоящему понять синтаксис template <typename, typename...> class Container
. То, что находится в <
>
, кажется другим языком (по сравнению с C / старым C ). Может кто-нибудь, пожалуйста, объяснить это или дать хорошую ссылку, которая объясняет это?
template <typename T, template <typename, typename...> class Container>
static bool contained(const T amp; x, const Container<T> amp; xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
Комментарии:
1. Возможно, вам покажется интересной эта небольшая модификация (смотрите Здесь) . И обратите внимание, что это не будет компилироваться с привязкой clang3.4 к libc (но будет работать связанный libstdc ). Разница заключается в том, как
std::list
это реализовано. Добавление пакета переменных параметров решает эту проблему, и результат по сравнению с первым заслуживает изучения (смотрите Здесь) .2. Действительно. Это полезно знать.
Ответ №1:
template <typename T, template <typename, typename...> class Container>
Выше указано, что Container
это шаблон-параметр шаблона, что означает, что Container
тип, который вы передаете шаблону функции, сам должен быть шаблоном, который принимает по крайней мере один аргумент шаблона — второй аргумент шаблона и далее будет использоваться пакетом параметров ( typename...
).
Но есть проблема с вашим шаблоном функции. Как я объяснил, вы указываете, что Container
должен быть шаблон класса, который принимает один или несколько аргументов шаблона, но затем соответствующий параметр функции ( xs
) указывает, что он принимает один аргумент шаблона. Причина, по которой это работает с std::list
, или std::vector
, или std::deque
заключается в том, что их соответствующие вторые аргументы шаблона, тип распределителя, имеют значение по умолчанию ( std::allocator<T>
). Ваш шаблон функции не будет работать с одним из этих контейнеров, если они имеют тип распределителя, отличный от стандартного.
Чтобы исправить это, тип xs
также должен учитывать дополнительные аргументы шаблона.
template <typename T, typename... Params,
template <typename, typename...> class Container>
static bool contained(const T amp; x, const Container<T, Params...> amp; xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
Эта конкретная проблема, однако, может быть решена без использования параметров шаблона шаблона. Просто примите любой тип Container
вместо того, чтобы ставить условия о том, что он является шаблоном. Тип элемента, который вы ищете, может быть указан с помощью Container::value_type
вложенного типа, который определяют все контейнеры в стандартной библиотеке.
template <typename Container>
static bool contained(typename Container::value_type constamp; x,
const Containeramp; xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
Также добавлен C 11, std::any_of
который выполняет то же самое, что и ваша contained()
функция.