0

I've got a few functions, some of which are overloaded and some are templates, ex.:

void fun1 (vector<string> &a, int b);
void fun1 (vector<double> &a, int b);

template <typename t>
void fun2 (t a[], int b);

and so on. Every function I use has a version for 2 data types, one is an array and the other one is a vector (a vector of strings, a vector of doubles, an array of strings and an array of doubles). The question is, can I create a template for an array of pointers? Is there any way of doing it, apart from:

void (*strvecfun[])(vector <string>&, long, long)={fun1, fun2};
void (*dblvecfun[])(vector <double>&, long, long)={fun1, fun2};
void (*strarrfun[])(string [], long, long)={fun1, fun2};

and so on?

2
  • vector <string> a& that is a new syntax, or maybe a typo ;). [postreference]. Are you actually editing the length of the vectors in those functions? Or are you just editing elements? What if you didn't need 2 overloads? Commented Mar 17, 2015 at 18:27
  • Surely a typo, sorry about that ;) Nope, no length editing, all of the functions are sorting functions. Commented Mar 17, 2015 at 18:32

3 Answers 3

1

You can use

template<typename Func>
struct func_array {
  static Func *const data[];
};

template<typename Func>
Func *const func_array<Func>::data[] = { fun1, fun2 };

And later call

func_array<void(std::vector<double>&, long, long)>::data[0](dvec, l1, l2);
func_array<void(std::vector<string>&, long, long)>::data[1](svec, l1, l2);
// ...and so forth

This requires that there are matching overloads for all the signatures you're going to use of all functions you put into the list, naturally.

Sign up to request clarification or add additional context in comments.

5 Comments

This is something I was looking for. Is there any way to shorten the call though?
Well, you can say auto &foo = func_array<void(std::vector<double&>, long, long)>::data; and subsequently call foo[0](dvec, l1, l2); or so. And there are using declarations. You'll have to resolve the function type at some point, though, so that's about as good as it gets.
That's great, thanks a lot. It's more than enough for what I need
Oh, one more thing- how can I pass it to a function that accepts an array of pointers as an argument? As of now, I've been taught to use void function(void (*fun[])(vector <string>&, long), vector <string> &tab, long n) for example
With the above implementation, you could write a function void foo(void(*const arr[])(std::vector<double>&, long, long)); and call foo(func_array<void(std::vector<double>&, long, long>::data);. And there's always decltype, if you have an alias set up at that point (otherwise it doesn't make things much clearer).
1

Instead of having 2 implementations, have one. Have your data take an array_view<double>:

template<class T>
struct array_view {
  // can make this private:
  T* b = 0; T* e = 0;

  // core methods:
  T* begin() const { return b; }
  T* end() const { return e; }

  // utility methods:
  size_t size() const { return end()-begin(); }
  T& front() const { return *begin(); }
  T& back() const { return *std::prev(end()); }
  bool empty() const { return begin()==end(); }

  // core ctors:
  array_view(T* s, T* f):b(s),e(f) {};
  array_view()=default;
  array_view(array_view const&)=default;

  // derived ctors:
  array-view(T* s, size_t l):array_view(s, s+l) {};
  template<size_t N>
  array_view( T(&arr)[N] ):array_view(arr, N) {};
  template<size_t N>
  array_view( std::array<T,N>&arr ):array_view(arr.data(), N) {};
  template<class A>
  array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {};

  // extra ctors that fail to compile if `T` is not const, but
  // are mostly harmless even if `T` is not const, and useful if
  // `T` is const.  We could do fancy work to disable them, but
  // I am lazy:
  using non_const_T = std::remove_const_t<T>;
  template<class A>
  array_view( std::vector<non_const_T,A>const& v ):array_view(v.data(), v.size()) {};
  template<size_t N>
  array_view( std::array<non_const_T,N>const&arr ):array_view(arr.data(), N) {};
  array_view( std::initializer_list<non_const_T> il ):array_view(il.data(), il.size()) {};
};

array_view acts like a view into a container, and can be implicitly converted from a number of std containers as well as raw arrays.

void fun1 (array_view<std::string> a);

a.size() tells you how long it is, and it can be iterated over in a for(:) loop even.

std::vector<T>& is far more powerful than what you need. By using array_view, we only expose what you need (access to elements), and thus are able to take both an array and a container.

If you pass in a "real" C style array, it will auto-deduce the length. If you instead pass in a pointer (or a [] really-a-pointer array), you also have to pass the length like:

fun1( {ptr, length} );

Comments

0

Create a function called max that will return the value of the largest element in an array.

The arguments to the function should be the address of the array size.

Make this function into a template so it will work with an array of any numerical types.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.