синтаксис параметров шаблона с переменными значениями

#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() функция.