简体   繁体   中英

Template Template C++ Function

How do I write a template function that operates on a arbitrary container of a arbitrary type? For example how do I generalize this dummy function

template <typename Element>
void print_size(const std::vector<Element> & a)
{
    cout << a.size() << endl;
}

to

template <template<typename> class Container, typename Element>
void print_size(const Container<Element> & a)
{
    cout << a.size() << endl;
}

Here is a typical usage

std::vector<std::string> f;
print_size(f)

This give error

tests/t_distances.cpp:110:12: error: no matching function for call to ‘print(std::vector<std::basic_string<char> >&)’. I'm guessing I must tell the compiler something more specific about what types that are allowed.

What is this variant of template-use called and how do I fix it?

Is there a specific reason for you to use a template template? Why not just like this?

template <typename Container>
void print_size(Container const& a)
{
    cout << a.size() << endl;
}

In general, template templates aren't worth the trouble. In your particular case, there certainly is no use for them, and if you really need to access the member type, I suggest you bow to common practice and use a metafunction ( typename Container::value_type in this case).

I know that the question was asked long time ago , but i had same problem , and the solution is that you need to write

template <template <typename,typename> class Container, typename element, typename Allocator>
void print_size(Container<element, Allocator> & a)
{
    std::cout << a.size() << std::endl;
}

because the vector has two template parameters

The problem is that the vector template takes two type arguments, and your template accepts only template arguments that accept a single argument. The simplest solution is lifting a bit of the type safety and just using Container as a type:

template <typename Container>
void print_size( Container const & c ) {
   std::cout << c.size() << std::endl;
}

Possibly adding static checks (whatever the type Container is, it must have a value_type nested type that is Element ...) The alternative would be to make the template template argument match the templates that are to be passed (including allocator for sequences, allocator and order predicate for associative containers)...

Why ever use something like

template <template<typename> class Container, typename Element>
void print_size(const Container<Element> & a)
{
    cout << a.size() << endl;
}

? Use it in simpler way:

template<typename Container>
void print_size(const Container & a)
{
    cout << a.size() << endl;
}

When calling print_size(f) , you will call print_size with Container being vector<string> .

For these types of generic algorithms, I always prefer iterators, ie

template <typename IteratorType>
void print_size(IteratorType begin, IteratorType end) {
   std::cout << std::distance(begin, end) << std::endl;
}

To call:

std::vector<std::string> f;
print_size(f.begin(), f.end());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM