2

I have a function that needs to be able to work for different container types, for example

void foo(const std::vector<bar>& param1, const std::vector<double>& params2)

and

void foo(const std::list<bar>& param1, const std::list<double>& params2)

where bar is a class that I've written. The function body itself uses generic C++ standard library functions.

Is there a way I can templatise this? I have tried

template<typename T> void foo(const T<bar>&, const T<double>&)

But this gives the compiler error

error C2988: unrecognizable template declaration/definition

I'm using MSVC2015.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405

3 Answers3

4

You should declare T as template template parameter to indicate that it's a template-name (and needs arguments to be instantiated), e.g.

template<template <typename...> class T> 
void foo(const T<bar>&, const T<double>&);

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
4

There are basically three solutions:

  1. Use template template arguments.

  2. Use iterators (which is what the standard library itself uses)

  3. Use different templates for different arguments, and let the compiler deduce the actual types. With your function it would be something like

    template<typename T, typename U> void foo(const T&, const U&);
    

Solution 2 is the recommended one if you just need to iterate over the contents of the container. Solution 3 is the recommended one if you need access tot he container itself.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2) and 3) would also allow to use foo with `std::array`s, while in case of 1) one would need to create additional overload – W.F. Jul 10 '17 at 09:47
  • @W.F. Solution 2 works with *any* container (even plain arrays or dynamically allocated memory). Solution 3 works with any container that works with the member-functions called. – Some programmer dude Jul 10 '17 at 09:50
0

So-called template template arguments will allow you to write the desired code (as also shown in other answers or over on CppReference).

Alternatively, you could also write generic functions that accept iterators. This is exactly how the functions in the <algorithm> are implemented. I tend to believe that functions that accept iterators are actually more flexible as the caller can decide what range needs to be processed by the function.

Maarten Bamelis
  • 2,243
  • 19
  • 32