Custom array-like type in c++ - c++

In a program I am writing, I need to use often integer arrays of length 3 and I thought I should define a custom type. The integers they will hold are between 0 and 2, so int8 is more than enough. My goal is to avoid having to check explicitly for length.
I could do something of the form:
class MyArr {
int8_t a;
int8_t b;
int8_t c;
}
but I would also like to be able to access the elements using [], e.g. to be able to write x[0] instead of x.a. What is the optimal way to do that?
Also I guess I have to check that the values are legal, i.e. between 0 and 2 in the constructor. Is there any better way?

I think the best way is to use std::array and if you want bounds checking you can use the at() function instead of operator[].
https://en.cppreference.com/w/cpp/container/array/at
Example:
#include <array>
std::array<int8_t, 3> data = { 1, 2, 4 };
// Set element 1
data.at(1) = 88;

Use an array. Use std::array if you want value semantics. If you use this type very often and want a name more meaningful than a generic "array", you can use a type alias:
// Example with a 3D vector
using vec3D = std::array<std::int8_t, 3>;
vec3D v1, v2; // 3D vectors

Related

C++ trying to create a queue of 2d points (arrays)

I am trying to create a queue of 2d points, like this:
queue<int[2]> q;
this compiles, however, after doing:
q.push({0,0});
I get an compile error, saying that my call to push is ambiguous. Not sure how to fix this. Please help.
I'm not sure if this is a good way to represent 2d points on a plane, but it seems to me to be the most lightweight.
You can use Pair to represent your points.
queue<pair<int,int>>q;
q.push({0,0});
You can create a structure for the 2D points:
struct Point2D {
int x;
int y;
};
And you can create a std::vector instead of std::queue.
std::vector<Point2D> q {{ {1, 2}, {9, 3}, ... }};
And you can normally:
q.push_back({0, 0});
EDIT:
You can also create a vector of int[2] instead of Point2D and do the same thing.
You can always create a struct to hold your point coordinates. It's actually a good idea to have a representation for such entity regardless of your current problem.
The answer below is a more general one regarding arrays in c++, and does not require a custom struct:
In c++ it's usually recomended to use std::array instead of such small fixed size c style arrays (and std::vector for dynamic size ones).
Code example:
#include <queue>
#include <array>
int main() {
std::queue<std::array<int,2>> q;
q.push({ 0,0 });
return 0;
}
A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
Array are just pointers. Raw C arrays cannot be stored in container.
Solution 1: Use type of stored element as int*
std::queue<int*> q1;
int s1[2]{0,0};
q1.push(s1);
Solution 2: Use other container like std::array or std::vector
std::queue<std::array<int,2>> q;
q.push({0,0});

need to create multiple dynamic arrays in c++

I need to create a number of arrays of a certain object where the number I need is dependent on a separate variable the best way to explain it is with a psudo code example:
int num = 4;
for(int i=0;i<num;i++){
object_type arrayi [dynamic size];
}
So i need 4 arrays each with the names array0,array1,array2, and array3 and they must all be dynamic arrays.
Is there anyway to do this in C++?
std::array<std::vector<object_type>, 4> array;
for (auto & v : array)
v.resize(dynamic_size);
The names are array[0], array[1], etc... instead of array1, array2, etc... But who cares? If you absolutely must have those names, then Cassio's answer is your best bet.
Pre C++11 alternative:
std::vector<object_type> array[4];
for (size_t i=0; i<4; ++i)
array[i].resize(dynamic_size);
If you want a variable number of arrays, then you can use a vector of vectors, and actually, the initialization for that is even easier. It doesn't require a loop, you can do it in the constructor.
std::vector<std::vector<object_type>> array(num, std::vector<object_type>(dynamic_size));
Yes, use std::vector<object_type> instead. You can resize to an arbitrary size.
Otherwise for arrays you can use dynamic allocation with
ObjectType* myArray = new ObjectType[number];
but using std::vector instead is recommended.
If there is a way to dynamically create variables like the way you want within C++, I haven't heard of it.
If performance is an issue and you need to construct a bunch of 1-d arrays (rather than an array of arrays or a vector of arrays) then you could do code generation at build time to make as many as you want. That's outside of C++ though; it's a pre-build command that outputs a C++ text file.
If performance isn't an issue, then constructing a vector of arrays like Benjamin has done will work great.
Reading the OP again, it seems to me that the number of arrays is not known at compile time. In this case, you can use a std::vector<std::vector<object_type>>:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<std::vector<object_type>> vs(num);
for (auto& v: vs)
v.resize(dynamic_size);
then you can use vs[i][j] to get a reference to the j-th element of the i-th array (vector).
Piece of advise: Don't use this (std::vector<std::vector<double>>) for linear algebra matrices.
Bonus: In C++14 (actually this is a C99 feature that some compilers allow in C++ as an extension) you'll be able to do this:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<object_type> vs[num];
for (auto& v: vs)
v.resize(dynamic_size);
For more information see this post.

Multidimensional Containers in C++

Is there any library provide a multidimensional container to use like vector<>?
I would like to see something like:
TwoD<object_class_name> D2;
ThreeD<object_class_name> D3;
and the object_class_name could be any object instead of only the builtin types.
so I can use the object like
D2[i][j]
D3[i,j,k] or D3(i,j,k)
or similar
Thanks.
If c++11, a possible solution is using which allows aliasing of a template:
template <typename T>
using TwoD = std::vector<std::vector<T>>;
template <typename T>
using ThreeD = std::vector<std::vector<std::vector<T>>>;
usage:
TwoD<int> t2ints;
TwoD<std::string> t2strings;
ThreeD<int> t3ints;
ThreeD<std::string> t3strings;
boost::multi_array can do that.
2D array example:
boost::multi_array<float, 2> float2D(boost::extents[5][10]);
float2D[0][0] = 1.0f;
3D array example:
boost::multi_array<float, 3> float3D(boost::extents[5][10][20]);
float2D[0][0][0] = 1.0f;
The stored type can be a class or struct as well as a primitive type, and the memory used will be contiguous.
YOu could do something like this:
std::vector<std::vector<someType> > TwoDVector;
Or a two dimensional array like these:
someType** TwoDArrayPointer;
someType TwoDArray[size][size2];
I don't like vector<vector> because each row gets its own separately allocated memory block on the heap. This causes two problems:
Iterating over all elements of the array will have very poor cache performance compared to a contiguous 2D array.
You can't pass the array into a function that wants a 1D array. For example, a lot of imaging libraries only want a char * for image data.
Therefore, I would suggest writing your own 2D array template. It's a pretty simple task. Or you can use my public domain code at github.com/jpreiss/array2d .
Also note: you can't overload operator[] with a function that takes more than one parameter. You can overload operator() for 2D indexing.
You can use vector.
// Create
vector< vector<int> > vec(4, vector<int>(4));
// Write
vec[2][3] = 10;
// Read
int a = vec[2][3];

C++ - How do I put a static array inside my array?

I apologize for the total noob question, but I just cannot find an answer. I googled, searched here, searched C++ array documentation, and some C++ array tutorials.
The question is simple. Why does
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
... //do stuff. Imagine a loop here, and BIG array - I'm just simplifying it for StackOverflow
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
return 0;
}
result in an error?
1>arraytest.cpp(11): error C2059: syntax error : '{'
How do I put a static array inside my array? I realize I could set each item individually, but there has to be a better way.
Built-in arrays in C++ have their problems, and not being assignable does make them rather inflexible. I'd stick with std::array, a C++11 container that emulates a better style of array, which allows a somewhat similar syntax to what you're looking for:
std::array<int, 3> arr{{1, 2, 3}};
std::array<int, 3>{{4, 5, 6}}.swap(arr);
//now arr is {4, 5, 6}
Here's a full sample. The trick is to use the initializer list on a newly-constructed array and then swap that with yours. I believe that the next C++ update is going to remove the need for the double braces as well, which makes it an even closer match to familiar syntax.
Initializer lists can be used just for initialization :)
Like when you declare your variable:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}}; // this is ok
You have to remove this:
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
And assign new values manually (i.e. pixelarray[x][y] = or with a memcpy(pixelarray, <some other array>, sizeof(pixelarray)))
If you don't want to assign each individual element manually, you can do this:
short pixelarray2[3][3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
memcpy(pixelarray, pixelarray2, sizeof(pixelarray));
As #Nick points out: initializer lists are not for assignment.
Arrays are not assignable, so the short answer is that you can't do exactly what you're asking for. The most direct way to do something similar enough for most purposes is probably a 2D array class that acts as a wrapper around a std::vector, on the order of the one I posted in a previous answer.
If you insist on staying with C-style arrays, one possibility would be to use a pointer:
int main() {
typedef short array[3];
array pixelarray0[3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
array pixelarray1[3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
array *pixelarray = pixelarray0;
// when needed:
pixelarray = pixelarray1;
}
Taking this question from a straight C context, you can have different constant arrays and just copy them with memcpy:
typedef short TArray[3][3];
const TArray a1 = {{1,1,1},{0,0,0},{-1,-1,-1}};
const TArray a2 = {{1,0,-1},{1,0,-1},{1,0,-1}};
// ...
TArray a;
memcpy( a, a2, sizeof(TArray));
Or you could exploit C99 struct copying, but I'd consider this a dangerous hack because the structure might be padded to be larger than the array, or have a different alignment.
typedef struct {
TArray arr;
} TDummyArray;
// ...
TArray a;
*(TDummyArray*)a = *(TDummyArray*)a2;
Once you have declared your array there is no way to use the assignment operator to reassign the entire content of the array.
So to change the contents or your array after this:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
You need to either loop through the array and manually change each value, or you something like std::memcpy to copy your new values over.
But you should really not be using an array in the first place, use some fromthing the std collections library instead like std::array or std::vector. Only use arrays if you have a really really good reason why you can't use a collection.

How to convert a float pointer to an int pointer in C++?

I understand that reinterpret_cast may do it, but I think it did not do the data conversion. I don't want to loop over and do them one by one, and wonder whether there is an elegant way to do both the pointer type and data type conversion.
Thanks!
If, as I am assuming, you have some float* that points to the first element in an array of floats and you want to use them as ints then I suggest a few options:
If you don't want float, don't get floats. Just store an array of ints in the first place.
Likewise, if you don't want ints, then change your code to use floats throughout.
If you do indeed want to have an array of floats and at some point want to convert them to ints, do it when you need it. Use static_cast<int> to do the conversion on each element in a safe manner.
If you'd like to convert the whole array at once, then I suggest you do something like so:
float float_array[N] = /* ... */;
std::vector<int> ints(float_array, float_array + N);
Alternatively, if you really want to stick with arrays, use std::copy:
float float_array[N] = /* ... */;
int int_array[N];
std::copy(float_array, float_array + N, int_array);
The std::vector above is much preferred, however.