Best way to represent a array of std::optional in protobuf - c++

I need to map my "native" C++ struct that has an array(std::array, but I presume for std::vector solution is same) to protobuf.
So let' say I have
struct MyStruct{
// Color is some class I already know how to map to PB
std::array<std::optional<Color>, 4> opt_colors;
}
I am not sure what is the best way.
My current best guess is:
message ColorPb{
// some fields here
}
message OptColorPb{
int32 idx = 1; // idx in array
ColorPb color = 2; // value
}
message MyStructPb{
// in case of vector I would also have a size, but for array it is known
repeated OptColorPb opt_colors = 1;
}

Related

Is there a way to declare a std::array of structs in a constructor?

I have a FIFO class who's width and depth I'd like to declare when a new FIFO is instantiated. I'd like to use a std::array as one of the elements in the FIFO record and make the FIFO a std::array of records but I haven't figured out a way to declare a std::array with a value passed into the constructor. I'd like to use std::array because it seems like a safer approach than using c style arrays but even when I try this with c style arrays, I can't figure out how to declare the arrays with values passed to the constructor. This is for an embedded app so if this is a dumb idea or there's a better way, I'd be happy to hear it.
Here's what I'd like to do but obviously the FIFORecord stuct can't see the width value passed to the constructor and I get a "non-type template argument is not a constant expression" error using the depth value to declare the array of FIFORecords in the constructor. Thanks.
class FIFO
{
struct FIFORecord
{
std::array<uint8_t, width> msg;
uint32_t timestamp;
};
public:
FIFO(const uint32_t depth, uint32_t width, string qID)
{
capacity = depth;
qWidth = width;
head = 0;
tail = -1;
count = 0;
qName = qID;
std::array<FIFORecord, depth> fifoStack;
}

Calculate length of double pointer array

I have a double pointer Array of a structure:
typedef struct Position{
int x;
int y;
} Position;
Position** array = (Position**)malloc(sizeof(Position*)*10); //10 elements
array[0] = (Position*)malloc(sizeof(Position*));
array[0]->x = 10;
array[0]->y = 5;
Can I calculate the length of set array and if so, how?
The normal way for arrays does not work :
int length = sizeof(<array>)/sizeof(<array>[0]);
Once you have dynamically allocated an array, there is no way of finding out the number of elements in it.
I once heard of some hacky way to obtain the size of a memory block, (msize) which would allegedly allow you to infer the size of the data within the block, but I would advice against any such weird tricks, because they are not covered by the standard, they represent compiler-vendor-specific extensions.
So, the only way to know the size of your array is to keep the size of the array around. Declare a struct, put the array and its length in the struct, and use that instead of the naked array.
As you marked the question as C++, I would suggest that you use std::vector, then, after you "allocated some memory" (or requested some memory to allocated by std::vector constructor or by using push_back, or resize), you can simply get the size back using by using std::vector::size.
typedef struct Position{
int x;
int y;
} Position;
std::vector<Position> array(10);
array[0].x = 10;
array[0].y = 5;
size_t size = array.size(); // will be 10
Having only a pointer to some memory block, you cannot defer the size of this memory block. So you cannot defer the number of elements in it.
For arrays of pointers, however, you could infer the number of elements in it under the following conditions:
make sure that every pointer (except the last one) points to a valid object.
for the last pointer in the array, make sure that it is always NULL.
Then you can derive the length by counting until you reach NULL.
Maybe there are some other similar strategies.
Solely from the pointer itself, however, you cannot derive the number of elements in it.
Old question, but in case someone needs it:
#include <stdio.h>
...
int main()
{
char **double_pointer_char;
...
int length_counter = 0;
while(double_pointer_char[length_counter])
length_counter++;
...
return 0;
}

How to create new Type in MPI

I am new to MPI and I want to create a new datatype for Residence struct. I just want to see if I can create the new type right way.
struct Residence
{
double x;
double y;
};
My new MPI Type
MPI_Datatype createRecType()
{
// Set-up the arguments for the type constructor
MPI_Datatype new_type;
int count = 2;
int blocklens[] = { 1,1 };
MPI_Aint indices[2];
//indices[0]=0;
MPI_Type_extent( MPI_DOUBLE, &indices[0] );
MPI_Type_extent( MPI_DOUBLE, &indices[1] );
MPI_Datatype old_types[] = {MPI_DOUBLE,MPI_DOUBLE};
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
MPI_Type_commit(&new_type);
}
You've almost got it right except that indices is supposed to give the offset of each structure field in bytes from the beginning of the structure. The correct way to construct such a type would be to use the offsetof operator, defined in stddef.h:
#include <stddef.h> // or <cstddef> for C++
struct Residence
{
double x;
double y;
};
MPI_Datatype createRecType()
{
// Set-up the arguments for the type constructor
MPI_Datatype new_type;
int count = 2;
int blocklens[] = { 1,1 };
MPI_Aint indices[2];
indices[0] = (MPI_Aint)offsetof(struct Residence, x);
indices[1] = (MPI_Aint)offsetof(struct Residence, y);
MPI_Datatype old_types[] = {MPI_DOUBLE,MPI_DOUBLE};
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
MPI_Type_commit(&new_type);
return new_type;
}
While this would suffice for that particular structure, in general one has to adjust the structured type length in order to account for any trailing padding that the compiler might insert at the end of the structure. This is only necessary if one wants to send multiple items of that structured type, i.e. an array of structure elements. The old way to do that was to add a third member to the structure of type MPI_UB (UB comes from Upper Bound) and set the offset of that member to be equal to sizeof(struct Residence) (padding is accounted in the structure size as returned by sizeof). The modern way is to use MPI_Type_create_resized, which creates a new MPI type with the same type signature as the original one but with a different extent:
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
// Create a resized type
MPI_Type resized_new_type;
MPI_Type_create_resized(new_type,
// lower bound == min(indices) == indices[0]
indices[0],
(MPI_Aint)sizeof(struct Residence),
&resized_new_type);
MPI_Type_commit(&resized_new_type);
// Free new_type as it is no longer needed
MPI_Type_free(&new_type);
return resized_new_type;
Only the relevant code lines are shown. The code above assumes that indices[0] gives the offset of the first structure element. One could instead use MPI_Type_get_extent to get the true lower bound and that would work for structure types with negative offsets. It is not necessary to commit new_type as it is only used to construct the resized type. It is also not necessary to keep it around and that's why it is freed after resized_new_type has been created.

How to create multidimensional multitype c++ vector?

I'm looking for a way to create a C++ vector which will hold class object ( which is multi dimensional array - 3D coordinate system location mapper ) and int object which describes it in some way.
I have found many examples of multidimensional single type vectors like
vector <vector<int>> vec (4, vector<int>(4));
I need a dynamic structure which can grow/shrink in the heap as time progress with flexibility of the vector type.
// Your position object, whatever the declaration may be
struct Position { int x, y, z; };
struct Connection {
Position position;
int strength;
};
// This is what you want your node class to be
// based on the comment you gave.
struct Node {
Position position;
std::vector<Connection> connections;
};
// A vector is dynamic and resizable.
// Use std::vector::push_back and std::vector::emplace_back methods
// insert elements at the end, and use the resize method to modify
// the current size and capacity of the vector.
std::vector<std::vector<std::vector<Node>>> matrix;
An alternative would be to define a Connection as an std::pair<Position, int>, but that wouldn't be very good because if you wanted to add more information to the Connection in the future, you'd have to change more code than you should.
If you want to resize the whole multidimensional array, you'll have to iterate over all the vectors one by one with a loop and call the resize method.
You can only get "type flexibility" out of a std::vector is to have it store a polymorphic type. Based on your example, it looks like you may want a std::vector of structs:
struct s
{
int i;
double d;
char c;
bool b;
};
std::vector<s> vec;
// elements can be accessed as such:
auto i = vec[0].i;
auto d = vec[0].d;
auto c = vec[0].c;
auto b = vec[0].b;

C++ class for arrays with arbitrary indices

Do any of the popular C++ libraries have a class (or classes) that allow the developer to use arrays with arbitrary indices without sacrificing speed ?
To give this question more concrete form, I would like the possibility to write code similar to the below:
//An array with indices in [-5,6)
ArbitraryIndicesArray<int> a = ArbitraryIndicesArray<int>(-5,6);
for(int index = -5;index < 6;++index)
{
a[index] = index;
}
Really you should be using a vector with an offset. Or even an array with an offset. The extra addition or subtraction isn't going to make any difference to the speed of execution of the program.
If you want something with the exact same speed as a default C array, you can apply the offset to the array pointer:
int* a = new int[10];
a = a + 5;
a[-1] = 1;
However, it is not recommended. If you really want to do that you should create a wrapper class with inline functions that hides the horrible code. You maintain the speed of the C code but end up with the ability to add more error checking.
As mentioned in the comments, after altering the array pointer, you cannot then delete using that pointer. You must reset it to the actual start of the array. The alternative is you always keep the pointer to the start but work with another modified pointer.
//resetting the array by adding the offset (of -5)
delete [] (a - 5);
A std::vector<int> would do the trick here.
Random acess to a single element in a vector is only O(1).
If you really need the custom indices you can make your own small class based on a vector to apply an ofset.
Use the map class from the STL:
std::map<int, int> a;
for( int index = -5; index < 6; ++index )
{
a[index] = index;
}
map is implemented internally as a sorted container, which uses a binary search to locate items.
[This is an old thread but for reference sake...]
Boost.MultiArray has an extents system for setting any index range.
The arrays in the ObjexxFCL library have full support for arbitrary index ranges.
These are both multi-dimensional array libraries. For the OP 1D array needs the std::vector wrapper above should suffice.
Answer edited because I'm not very smart.
Wrap an std::vector and an offset into a class and provide an operator[]:
template <class T>
class ArbVector
{
private:
int _offset;
std::vector<T> container;
public:
ArbVector(int offset) : _offset(offset) {}
T& operator[](int n) { return container[n + _offset] }
};
Not sure if this compiles, but you get the idea.
Do NOT derive from std::vector though, see comments.