0

I want to pass a dynamic size standard and of typename type array to a function.

I can't figure out how to do it. Why can't I just accept a reference to the object array?

The code I tried:

#include <iostream> #include <array> using namespace std; template <typename T> void showArrays(void *myArrayPointer, int size, T type) { array<T, size> myArray = myArrayPointer; for (int i = 0; i < size; i++) { cout << myArray.at(i) << " \n"; } } int main() { array<int,6> myArray = { 1,2,3,4,5,6 }; cout << "The array is \n"; showArrays(&myArray,6,0); return 0; } 

But I get expected compile-time constant expression for the Size still. My function header is also not very pretty. But I couldn't figure out a way to have the size dynamic without passing a generic pointer or creating a template of the class array where the size is an attribute.

0

2 Answers 2

6

There is no reason to use a void* here at all. The type of the elements and size of a std::array are known at compile time and you can capture those using a template.

template<typename T, std::size_t N> void print_arry(const std::array<T, N>& arr) { for (const auto& e : arr) std::cout << e << "\n"; } 

Will capture any std::array and print its elements as long as they have an overloaded operator <<. You can also use T as the element type and N as the size of the array inside the function which lets you write a accumulate function like

template<typename T, std::size_t N> T print_arry(const std::array<T, N>& arr) { if (N == 0) return 0; T accum = arr[0]; for (std::size_t i = 1; i < N; ++i) accum += arr[i]; return accum; } 
Sign up to request clarification or add additional context in comments.

Comments

5

If you want a function template where the type is a template parameter, but the size is a runtime property (which could make sense if you want to avoid binary bloat), then you want something like this:

template <typename T> void showArrays(T* p, int n) { for (int i = 0; i < n; ++i) { std::cout << p[i] << '\n'; } } int main() { std::array<int, 6> myArray = { 1,2,3,4,5,6 }; std::cout << "The array is \n"; showArrays(myArray.data(), 6); // or use myArray.size() } 

You can reuse your template for other kinds of contiguous arrays, too:

float a[] = { 1.1, 2.2, 3.3, 4.4 }; showArrays(a, 4); // full array showArrays(a + 1, 2); // just the middle two std::vector<long> v = /* ... */; showArrays(v.data(), v.size()); std::string s = "hello world"; showArrays(s.data() + 6, 5); 

Note that T is a template parameter and not a function parameter. Note further that we never specify an argument for the parameter: that's because the argument is deduced. If you did want to pass a void pointer, like you did in your example, then you would not be able to deduce the template argument from the function call, and you'd have to specify it explicitly:

template <typename T> void showArrays(void* p, int n) { // ^^^^^ for (int i = 0; i < n; ++i) { std::cout << static_cast<T*>(p)[i] << '\n'; // ^^^^^^^^^^^^^^^^^^ // cast to object pointer, // note that "T" shows up in your code now! } } showArrays<int>(myArray.data(), myArray.size()); // ^^^^^ // explicit template argument 

1 Comment

This is the right answer. I couldn't figure out what he was trying to do.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.