I have a templated function func as follows which takes two parameters of the same type (usually two STL containers of the same type but different sizes). I want to make it work with C-arrays of the same type but different sizes too.
template<class T>
void func(const T& a, const T& b) {
// some code like as follows
for(auto x : a) {
cout << x << " ";
}
cout << endl;
for(auto x : b) {
cout << x << " ";
}
}
Obviously, the following code fails with error: no matching function for call to 'func(int [2], int [3])':
int a1[] = {1, 2};
int a2[] = {3, 4, 5};
func(a1, a2);
I cannot alter the function signature but I can overload it. I also want to avoid unnecessary copies too. My attempt was to write an overload like:
template<class T, size_t M, size_t N>
void func(const T (&a)[M], const T (&b)[N]) {
//somehow calling f<T>(const T&, const T&) without copying array elements
}
But, I am not sure how to implement it. Any ideas are welcome. Thanks!
Live demo based on this answer.
You need to make a range<T*> structure to wrap your array, and define begin() and end() functions for it.
It can be as simple as
template<typename Iterator>
struct range { Iterator begin_, end_; };
template<typename T>
T begin(const range<T>& ar) { return ar.begin_; }
template<typename T>
T end(const range<T>& ar) { return ar.end_; }
template<typename T, size_t N>
range<T*> make_array_range(T (&array)[N])
{
using std::begin; using std::end;
return { begin(array), end(array) };
}
func( make_array_range(a1), make_array_range(a2) );
You can then easily write your func(T[N], T[M]) overload using this building block.
You could also write a templated (on N) constructor if you don't like the factory function approach.
It can be used in place of any standard container because it supports the begin/end operations. And it can refer to a whole array, contiguous subset of an array, or to a contiguous subsequence of any standard container.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With