Reputation: 22460
I have this template function (I remember seeing similar things somewhere from SO). It works on both std::function
and std::list
(as Container
). But I can't really understand the syntax template <typename, typename...> class Container
. What's in the <
>
seems to be a different language (compared to C/old C++). Can someone please explain it or give a good reference that explains this?
template <typename T, template <typename, typename...> class Container>
static bool contained(const T & x, const Container<T> & xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
Upvotes: 1
Views: 130
Reputation: 109089
template <typename T, template <typename, typename...> class Container>
The above indicates that Container
is a template template-parameter, which means that the Container
type that you pass to the function template must itself be a template that takes at least one template argument - the second template argument onwards will be consumed by the parameter pack (typename...
).
But there's a problem with your function template. As I explained, you indicate that Container
must be a class template that takes one or more template arguments, but then the corresponding function parameter (xs
) indicates it takes a single template argument. The reason this works with std::list
, or std::vector
, or std::deque
is because their respective second template arguments, the allocator type, has a default value (std::allocator<T>
). Your function template will not work with one of these containers if they have a non-default allocator type.
To fix it, the type of xs
needs to accommodate the extra template arguments also.
template <typename T, typename... Params,
template <typename, typename...> class Container>
static bool contained(const T & x, const Container<T, Params...> & xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
This particular problem can, however, be solved without the use of template template parameters. Just accept any type Container
instead of placing stipulations on it being a template. The type of the element you're searching for can be specified by using the Container::value_type
nested type that all containers in the standard library define.
template <typename Container>
static bool contained(typename Container::value_type const& x,
const Container& xs) {
return std::find(xs.begin(),xs.end(),x) != xs.end();
}
Also, C++11 added std::any_of
which does the same thing as your contained()
function.
Upvotes: 2