Known array / pointer size as argument - c++

InputManager* input = new InputManager(new int[]{ SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT });
I wanna pass this array of keys (or a pointer to it) but i need the InputManager's constructor to know its size. Since its known at compile time how would i get it?
Online i found this template
template <int N>
InputManager::InputManager(int (&keyArray)[N]) {
this->maxKeys = N;
this->keys = keyArray;
}
But i get an error that the arguments dont match.
I need any possible solution where i dont need to manually write the length. So macros, templates or anything else is accepted.

Don't use so many pointers. It's not healthy and you're likely to either leak memory, or try to free memory that you can't (if you didn't pass a newly-allocated array). Here's a minimal modification of your code:
class InputManager {
public:
template <int N>
InputManager(int (&keyArray)[N])
: maxKeys(N), keys(std::make_unique<int[]>(N))
{
std::copy_n(keyArray, N, keys.get());
}
private:
std::size_t maxKeys;
std::unique_ptr<int[]> keys;
};
int main() {
int keys[] = { 1, 5, 4, 7, 2 };
InputManager input {keys};
}
This compiles (GodBolt).
Notes:
This way, you don't need to write a custom destructor; although you would need to write an assignment operator which copies data; and a copy constructor.
It's probably better to just use an std::vector internally (or std::array if you know the input size beforehand), and take any span or range of keys in the constructor.

Wrap creating of this array into function using variadic template.
If you want only return a pointer to array:
template<class ... enums>
int* makeArray (enums ... e) {
return new int[sizeof...(e)]{e...};
}
When you want to know size of returned array you can return pair:
template<class ... enums>
std::pair< int*, size_t > makeArray2(enums ... e) {
constexpr size_t N = sizeof...(e);
return std::make_pair( new int[N]{e...}, N);
}

Related

Why is alloca returning the same address twice?

I'm trying to implement my own math library, and I'm starting off with vectors. The idea is to give the class a pointer to an array of numbers, then copy the array and store it in the data address given by a private variable pointer. To begin with, I used alloca to try and free up some memory for the private variable
vml.h
namespace vml {
// Vectors
template <typename in_type, const int in_length>
class vec {
public:
vec(in_type* in_data) {
std::cout << data << std::endl;
std::copy(in_data, in_data + in_length, data);
}
vec() {
data = nullptr;
}
in_type& operator()(int index) const {
_ASSERT(0 <= index && index < in_length);
return data[index];
}
private:
in_type* data = alloca(in_length * sizeof(in_type));
};
main.cpp
int main() {
int list[] = { 1,2,3 };
int list2[] = {2,4,6 };
vml::vec<int, 3> a(list);
vml::vec<int, 3> b(list);
return 0;
}
This gives no errors however, for some reason, alloca returns the same address twice when calling two instances. I searched this up everywhere and I couldn't find an explanation why. So I decided to allocate memory using an array. If you can answer this question that would be extremely helpful.
Thanks.
You have to be very careful with alloca. It allocates memory on the stack rather than the heap. That memory is freed as soon as the function which called alloca exits. In this case, it will be called in the constructor so when you call operator() that memory has already been freed and you are dealing with undefined behavior.
Unless you really need to avoid heap allocations and you know for sure that you wont overflow the stack and you understand all the limitations of using alloca, it's best to steer clear of it.
Lets start with the basics, your stack is most likely only 1 MB, so after a few vectors and recursive calls you program will likely die.
To solve it if you want it on stack you could use std::array as data
Warning untested code ahead
template <typename in_type, const int in_length>
class vec {
public:
vec(in_type* in_data) {
std::cout << data << std::endl;
std::copy(in_data, in_data + in_length, data);
}
vec() = default;
in_type& operator()(int index) const {
_ASSERT(0 <= index && index < in_length);
return data[index];
}
private:
std::array<in_type, in_length> data;
};
Alternatively if you want to use all the nice things from std::array
template <typename in_type, const int in_length>
class vec : public std::array<in_type, in_length> {
public:
using std::array::array; // use constructors, might need template param to compile
}
This also means that if you at some point just want to change to heap you just allocate your vec as every other class.
Another alternative is to use C++17 PMR, use an allocation on the stack as the storage and make vec PMR aware.
You cannot wrap alloca in a function and return its pointer outside, since the stack of wrapper function would be freed.
If you call it as member initializer, it is actually called from constructor, and may be freed when constructor returns and then re-used.

Variable array dimension at runtime C++

I'm trying to create a program that can read some data from 2 files.
The first file is the header, that describe the data structure (dimensions, data type, extents, etc...), and the second is the raw data.
To handle different data type at runtime, I created a templated class that will be used as a container for the data. Depending on the data type read in the header, I will create a specialized class of the container to store the data.
However, now I'm facing another issue. How can I create a dynamic multidimensional array at runtime ?
I first thought doing it the old fashion way, and put a pointer into the storage class, and creating some loops ( = to the dimensionality) to create a new array (new array[size]).
But I don't think it's a very clean way of doing it.
I also thought about stacking std::vector, but I don't know the dimensionnality before runtime.
Then I considered using boost to create a multi_array, and using resize() to update the extent of my array at runtime, but it is required to know the dimension when creating the array (multi_array< type, dim > variable).
As I want to be able to access this in all my class (for future processing, etc...), I don't see how to put that in my class, as I will only know the dimensionnality at runtime.
Is it possible to create a base pointer of multi_array in my class, and declare it later (when I will know the dimension needed) ?
Or is there another way to do this ?
My final goal is to create a multidimensional array at runtime, that I can access in all my class.
Thank you.
Edit: Most of the topics I read about it are for fixed dimensional array, with a variating size. But in my case, dimension also varies.
Update: Your answer inspired me an idea Hugues.
I already have a templated class to read the data, but for now it only takes as parameter, the data type.
I'm thinking adding the dimensionnality to it and create a class like that:
storageClass< data_type, data_dimension > myStorage(filename, data_extent, data_endian, data_encoding);
This way, I can also template the dimensionnality of the data, and create a multidimensionnal array (using boost for example).
I will let you know if it worked.
Thank you.
Update 2: Apparently it's not possible cause templates expect constant expression. I cannot pass the variable 'dimension' (even if it's a fixed value in this case, but it's not define at compile-time).
So I guess my best option is to create a variadic getter in the custom storage class, and return the corresponding value. The problem is that a variadic method involve to parse the arguments, and as this is a method that will be frequently called, it's not optimal.
It is likely necessary to create a custom class.
One idea is to have it contain two main members m_dims and m_data:
#include <vector>
#include <cassert>
using std::size_t;
template<typename T> class MultiArray {
public:
MultiArray(const std::vector<int>& dims)
: m_dims(dims), m_data(product(m_dims)) { }
const std::vector<int>& dims() const { return m_dims; }
const T& operator[](const std::vector<int>& indices) const {
return m_data[index(indices)];
}
T& operator[](const std::vector<int>& indices) {
return m_data[index(indices)];
}
private:
std::vector<int> m_dims;
std::vector<T> m_data;
static size_t product(const std::vector<int>& dims) {
size_t result = 1;
for (size_t i = 0; i<dims.size(); ++i) result *= size_t(dims[i]);
return result;
}
size_t index(const std::vector<int>& indices) const {
size_t v = 0;
for (size_t i = 0; i<m_dims.size(); ++i) {
assert(indices[i]>=0 && indices[i]<m_dims[i]);
if (i) v *= size_t(m_dims[i]);
v += size_t(indices[i]);
}
return v;
}
};
int main() {
MultiArray<float> ar{std::vector<int>{2, 3}};
ar[std::vector<int>{0, 0}] = 1.f;
ar[std::vector<int>{0, 1}] = 2.f;
ar[std::vector<int>{0, 2}] = 3.f;
ar[std::vector<int>{1, 0}] = 4.f;
ar[std::vector<int>{1, 1}] = 5.f;
ar[std::vector<int>{1, 2}] = 6.f;
}
See code in http://coliru.stacked-crooked.com/a/92e597d4769f9cad

Why can't I wrap a T* in an std::vector<T>?

I have a T* addressing a buffer with len elements of type T. I need this data in the form of an std::vector<T>, for certain reasons. As far as I can tell, I cannot construct a vector which uses my buffer as its internal storage. Why is that?
Notes:
Please don't suggest I use iterators - I know that's usually the way around such issues.
I don't mind that the vector having to copy data around if it's resized later.
This question especially baffles me now that C++ has move semantics. If we can pull an object's storage from under its feet, why not be able to shove in our own?
You can.
You write about std::vector<T>, but std::vector takes two template arguments, not just one. The second template argument specifies the allocator type to use, and vector's constructors have overloads that allow passing in a custom instance of that allocator type.
So all you need to do is write an allocator that uses your own internal buffer where possible, and falls back to asking the default allocator when your own internal buffer is full.
The default allocator cannot possibly hope to handle it, since it would have no clue on which bits of memory can be freed and which cannot.
A sample stateful allocator with an internal buffer containing already-constructed elements that should not be overwritten by the vector, including a demonstration of a big gotcha:
struct my_allocator_state {
void *buf;
std::size_t len;
bool bufused;
const std::type_info *type;
};
template <typename T>
struct my_allocator {
typedef T value_type;
my_allocator(T *buf, std::size_t len)
: def(), state(std::make_shared<my_allocator_state, my_allocator_state>({ buf, len, false, &typeid(T) })) { }
template <std::size_t N>
my_allocator(T(&buf)[N])
: def(), state(std::make_shared<my_allocator_state, my_allocator_state>({ buf, N, false, &typeid(T) })) { }
template <typename U>
friend struct my_allocator;
template <typename U>
my_allocator(my_allocator<U> other)
: def(), state(other.state) { }
T *allocate(std::size_t n)
{
if (!state->bufused && n == state->len && typeid(T) == *state->type)
{
state->bufused = true;
return static_cast<T *>(state->buf);
}
else
return def.allocate(n);
}
void deallocate(T *p, std::size_t n)
{
if (p == state->buf)
state->bufused = false;
else
def.deallocate(p, n);
}
template <typename...Args>
void construct(T *c, Args... args)
{
if (!in_buffer(c))
def.construct(c, std::forward<Args>(args)...);
}
void destroy(T *c)
{
if (!in_buffer(c))
def.destroy(c);
}
friend bool operator==(const my_allocator &a, const my_allocator &b) {
return a.state == b.state;
}
friend bool operator!=(const my_allocator &a, const my_allocator &b) {
return a.state != b.state;
}
private:
std::allocator<T> def;
std::shared_ptr<my_allocator_state> state;
bool in_buffer(T *p) {
return *state->type == typeid(T)
&& points_into_buffer(p, static_cast<T *>(state->buf), state->len);
}
};
int main()
{
int buf [] = { 1, 2, 3, 4 };
std::vector<int, my_allocator<int>> v(sizeof buf / sizeof *buf, {}, buf);
v.resize(3);
v.push_back(5);
v.push_back(6);
for (auto &i : v) std::cout << i << std::endl;
}
Output:
1
2
3
4
6
The push_back of 5 fits into the old buffer, so construction is bypassed. When 6 is added, new memory is allocated, and everything starts acting as normal. You could avoid that problem by adding a method to your allocator to indicate that from that point onward, construction should not be bypassed any longer.
points_into_buffer turned out to be the hardest part to write, and I've omitted that from my answer. The intended semantics should be obvious from how I'm using it. Please see my question here for a portable implementation in my answer there, or if your implementation allows it, use one of the simpler versions in that other question.
By the way, I'm not really happy with how some implementations use rebind in such ways that there is no avoiding storing run-time type info along with the state, but if your implementation doesn't need that, you could make it a bit simpler by making the state a template class (or a nested class) too.
The short answer is that a vector can't use your buffer because it wasn't designed that way.
It makes sense, too. If a vector doesn't allocate its own memory, how does it resize the buffer when more items are added? It allocates a new buffer, but what does it do with the old one? Same applies to moving - if the vector doesn't control its own buffer, how can it give control of this buffer to another instance?
These days - you no longer need to wrap a T* in an std::vector, you can wrap it with an std::span (in C++20; before that - use gsl::span). A span offers you all the convenience of a standard library container - in fact, basically all relevant features of std::vector excluding changes to the size - with a very thin wrapper class. That's what you want to use, really.
For more on spans, read: What is a "span" and when should I use one?

Calling templated function with type unknown until runtime

I have a this function to read 1d arrays from an unformatted fortran file:
template <typename T>
void Read1DArray(T* arr)
{
unsigned pre, post;
file.read((char*)&pre, PREPOST_DATA);
for(unsigned n = 0; n < (pre/sizeof(T)); n++)
file.read((char*)&arr[n], sizeof(T));
file.read((char*)&post, PREPOST_DATA);
if(pre!=post)
std::cout << "Failed read fortran 1d array."<< std::endl;
}
I call this like so:
float* new_array = new float[sizeof_fortran_array];
Read1DArray(new_array);
Assume Read1DArray is part of a class, which contains an ifstream named 'file', and sizeof_fortran_array is already known. (And for those not quite so familiar with fortran unformatted writes, the 'pre' data indicates how long the array is in bytes, and the 'post' data is the same)
My issue is that I have a scenario where I may want to call this function with either a float* or a double*, but this will not be known until runtime.
Currently what I do is simply have a flag for which data type to read, and when reading the array I duplicate the code something like this, where datatype is a string set at runtime:
if(datatype=="float")
Read1DArray(my_float_ptr);
else
Read1DArray(my_double_ptr);
Can someone suggest a method of rewriting this so that I dont have to duplicate the function call with the two types? These are the only two types it would be necessary to call it with, but I have to call it a fair few times and I would rather not have this duplication all over the place.
Thanks
EDIT:
In response to the suggestion to wrap it in a call_any_of function, this wouldnt be enough because at times I do things like this:
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_stuff(my_double_ptr);
}
// More stuff happening in between
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_different_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_different_stuff(my_double_ptr);
}
If you think about the title you will realize that there is a contradiction in that the template instantiation is performed at compile time but you want to dispatch based on information available only at runtime. At runtime you cannot instantiate a template, so that is impossible.
The approach you have taken is actually the right one: instantiate both options at compile time, and decide which one to use at runtime with the available information. That being said you might want to think your design.
I imagine that not only reading but also processing will be different based on that runtime value, so you might want to bind all the processing in a (possibly template) function for each one of the types and move the if further up the call hierarchy.
Another approach to avoid having to dispatch based on type to different instantiations of the template would be to loose some of the type safety and implement a single function that takes a void* to the allocated memory and a size argument with the size of the type in the array. Note that this will be more fragile, and it does not solve the overall problem of having to act on the different arrays after the data is read, so I would not suggest following this path.
Because you don't know which code path to take until runtime, you'll need to set up some kind of dynamic dispatch. Your current solution does this using an if-else which must be copied and pasted everywhere it is used.
An improvement would be to generate a function that performs the dispatch. One way to achieve this is by wrapping each code path in a member function template, and using an array of member function pointers that point to specialisations of that member function template. [Note: This is functionally equivalent to dynamic dispatch using virtual functions.]
class MyClass
{
public:
template <typename T>
T* AllocateAndRead1DArray(int sizeof_fortran_array)
{
T* ptr = new T[sizeof_fortran_array];
Read1DArray(ptr);
return ptr;
}
template <typename T>
void Read1DArrayAndDoStuff(int sizeof_fortran_array)
{
Do_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
template <typename T>
void Read1DArrayAndDoOtherStuff(int sizeof_fortran_array)
{
Do_different_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
// map a datatype to a member function that takes an integer parameter
typedef std::pair<std::string, void(MyClass::*)(int)> Action;
static const int DATATYPE_COUNT = 2;
// find the action to perform for the given datatype
void Dispatch(const Action* actions, const std::string& datatype, int size)
{
for(const Action* i = actions; i != actions + DATATYPE_COUNT; ++i)
{
if((*i).first == datatype)
{
// perform the action for the given size
return (this->*(*i).second)(size);
}
}
}
};
// map each datatype to an instantiation of Read1DArrayAndDoStuff
MyClass::Action ReadArrayAndDoStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoStuff<double>),
};
// map each datatype to an instantiation of Read1DArrayAndDoOtherStuff
MyClass::Action ReadArrayAndDoOtherStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoOtherStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoOtherStuff<double>),
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch(ReadArrayAndDoStuffMap, "float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch(ReadArrayAndDoOtherStuffMap, "double", 542);
}
If performance is important, and the possible set of types is known at compile time, there are a few further optimisations that could be performed:
Change the string to an enumeration that represents all the possible data types and index the array of actions by that enumeration.
Give the Dispatch function template parameters that allow it to generate a switch statement to call the appropriate function.
For example, this can be inlined by the compiler to produce code that is (generally) more optimal than both the above example and the original if-else version in your question.
class MyClass
{
public:
enum DataType
{
DATATYPE_FLOAT,
DATATYPE_DOUBLE,
DATATYPE_COUNT
};
static MyClass::DataType getDataType(const std::string& datatype)
{
if(datatype == "float")
{
return MyClass::DATATYPE_FLOAT;
}
return MyClass::DATATYPE_DOUBLE;
}
// find the action to perform for the given datatype
template<typename Actions>
void Dispatch(const std::string& datatype, int size)
{
switch(getDataType(datatype))
{
case DATATYPE_FLOAT: return Actions::FloatAction::apply(*this, size);
case DATATYPE_DOUBLE: return Actions::DoubleAction::apply(*this, size);
}
}
};
template<void(MyClass::*member)(int)>
struct Action
{
static void apply(MyClass& object, int size)
{
(object.*member)(size);
}
};
struct ReadArrayAndDoStuff
{
typedef Action<&MyClass::Read1DArrayAndDoStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoStuff<double>> DoubleAction;
};
struct ReadArrayAndDoOtherStuff
{
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<double>> DoubleAction;
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch<ReadArrayAndDoStuff>("float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch<ReadArrayAndDoOtherStuff>("double", 542);
}

Determine array size in constructor initializer

In the code below I would like array to be defined as an array of size x when the Class constructor is called. How can I do that?
class Class
{
public:
int array[];
Class(int x) : ??? { }
}
You folks have so overcomplicated this. Of course you can do this in C++. It is fine for him to use a normal array for efficiency. A vector only makes sense if he doesn't know the final size of the array ahead of time, i.e., it needs to grow over time.
If you can know the array size one level higher in the chain, a templated class is the easiest, because there's no dynamic allocation and no chance of memory leaks:
template < int ARRAY_LEN > // you can even set to a default value here of C++'11
class MyClass
{
int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure! Works like you imagine!
}
// Then you set the length of each object where you declare the object, e.g.
MyClass<1024> instance; // But only works for constant values, i.e. known to compiler
If you can't know the length at the place you declare the object, or if you want to reuse the same object with different lengths, or you must accept an unknown length, then you need to allocate it in your constructor and free it in your destructor... (and in theory always check to make sure it worked...)
class MyClass
{
int *array;
MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }
~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
}
You can't initialize the size of an array with a non-const dimension that can't be calculated at compile time (at least not in current C++ standard, AFAIK).
I recommend using std::vector<int> instead of array. It provides array like syntax for most of the operations.
Use the new operator:
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
I don't think it can be done. At least not the way you want. You can't create a statically sized array (array[]) when the size comes from dynamic information (x).
You'll need to either store a pointer-to-int, and the size, and overload the copy constructor, assignment operator, and destructor to handle it, or use std::vector.
class Class
{
::std::vector<int> array;
Class(int x) : array(x) { }
};
Sorry for necroing this old thread.
There is actually a way to find out the size of the array compile-time. It goes something like this:
#include <cstdlib>
template<typename T>
class Class
{
T* _Buffer;
public:
template<size_t SIZE>
Class(T (&static_array)[SIZE])
{
_Buffer = (T*)malloc(sizeof(T) * SIZE);
memcpy(_Buffer, static_array, sizeof(T) * SIZE);
}
~Class()
{
if(_Buffer)
{
free(_Buffer);
_Buffer = NULL;
}
}
};
int main()
{
int int_array[32];
Class<int> c = Class<int>(int_array);
return 0;
}
Alternatively, if you hate to malloc / new, then you can create a size templated class instead. Though, I wouldn't really recommend it and the syntax is quite ugly.
#include <cstdio>
template<typename T, size_t SIZE>
class Class
{
private:
T _Array[sz];
public:
Class(T (&static_array)[SIZE])
{
memcpy(_Array, static_array, sizeof(T) * SIZE);
}
};
int main()
{
char int_array[32];
Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
return 0;
}
Anyways, I hope this was helpful :)
I had the same problem and I solved it this way
class example
{
int *array;
example (int size)
{
array = new int[size];
}
}
Don't you understand there is not need to use vector, if one wants to use arrays it's a matter of efficiency, e.g. less space, no copy time (in such case if handled properly there is not even need to delete the array within a destructor), etc. wichever reasons one has.
the correct answer is: (quoted)
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
Do not try to force one to use non optimal alternatives or you'll be confusing unexperienced programmers
Instead of using a raw array, why not use a vector instead.
class SomeType {
vector<int> v;
SomeType(size_t x): v(x) {}
};
Using a vector will give you automatic leak protection in the face of an exception and many other benefits over a raw array.
Like already suggested, vector is a good choice for most cases.
Alternatively, if dynamic memory allocation is to be avoided and the maximum size is known at compile time, a custom allocator can be used together with std::vector or a library like the embedded template library can be used.
See here: https://www.etlcpp.com/home.html
Example class:
#include <etl/vector.h>
class TestDummyClass {
public:
TestDummyClass(size_t vectorSize) {
if(vectorSize < MAX_SIZE) {
testVector.resize(vectorSize);
}
}
private:
static constexpr uint8_t MAX_SIZE = 20;
etl::vector<int, MAX_SIZE> testVector;
uint8_t dummyMember = 0;
};
You can't do it in C++ - use a std::vector instead:
#include <vector>
struct A {
std::vector <int> vec;
A( int size ) : vec( size ) {
}
};
Declare your array as a pointer. You can initialize it in the initializer list later through through new.
Better to use vector for unknown size.
You might want to look at this question as well on variable length arrays.