How to write a function that can take in an array or a vector? How to write a function that can take in an array or a vector? arrays arrays

How to write a function that can take in an array or a vector?


If you expect to just be able to do func(v) you cannot, because there's no way I can think of that your function could deduce the size of the dynamically allocated int[numElements].

A good way you could wrap this is to take a pair of forward iterators, that is, if you only need iterating over items one by one, since random access is very bad on some containers like std::list.

template<class FWIt>void func(FWIt a, const FWIt b){    while (a != b)    {        std::cout << "Value: " << *a << '\n';        ++a;    }}template<class T>void func(const T& container){    using std::begin;    using std::end;    func(begin(container), end(container));}

This would work with the following:

int array[5] = {1, 2, 3, 4, 5};func(array);int* dynarray = new int[5]{1, 2, 3, 4, 5};func(dynarray, dynarray + 5);std::vector<int> vec{1, 2, 3, 4, 5};func(vec);func(vec.begin(), vec.end());std::list<int> list{1, 2, 3, 4, 5};func(list);

Edit: This also works by passing raw arrays directly rather than as two pointers thanks to @DanielH's change (but still won't work with dynamically allocated arrays).


span seems to be what you are looking for. Either wait for C++20 :-) or use span from the GSL. See What is a “span” and when should I use one?. Example below.

#include <array>#include <iostream>#include <vector>#if __cplusplus > 201709L#include <span>using std::span;#else#include <gsl/gsl>using gsl::span;#endifvoid func(span<int> data){    for(auto i : data){        std::cout << i << ' ';    }    std::cout <<'\n';}int main(){    std::vector<int> stdvec(3);    func(stdvec);    std::array<int,3> stdarr;    func(stdarr);    int carr[3];    func(carr);    int *ptr = new int[3]();    func({ptr,3});    delete []ptr;    return EXIT_SUCCESS;}


Would templating be the best way to accomplish this?

It depends. If you're writing a function that goes in a header, and thus can be used for further compilation later, then - yes, probably:

template <typename IntContainer>void f(Container& c);

or

template <typename IntContainer>void f(const Container& c);

However, if the implementation is compiled just once, you should consider:

void f(gsl::span<int> sp);

or

void f(gsl::span<const int> sp);

which uses a span. If you haven't heard about them, read:

What is a "span" and when should I use one?

this function will be able to take almost all of your variables as-is: The std::vector, the std::array and the plain (sized) array can be passed with no extra syntax. For the pointer, though, you will need to call something like f(gsl::make_span{ptr, numElements}).

PS - A third option, very common in the standard library, is to take interators, rather than the container, as the parameter. This would also require templating so it's similar to the first option.