Converting a struct to an array - c++

As programming becomes more complex, and the need to perform operations on struct data becomes visible. Is there a conversion method for converting a struct type into an array of its members such that:
struct FooDesc Foo{
int num_Foo;
int num_Bar;
int GreenFoo;
};
can be represented by:
int Bar[2];
Or better, dynamically as:
vector<int> Bar;
The goal is to convert or re-represent the data struct as an iteratable form, without the excessive use of the assignment operator.

You could use unnamed structs to make a hybrid struct where its member could be treated as an array:
struct Foo {
union {
struct {
int x;
int y;
int z;
};
struct {
int array[3];
};
};
};
LIVE DEMO
Note however, that unnamed struct comes from C11 and its not a standard C++ feature. It is supported as an extension though by GCC as well Clang.

If your structs are POD then you might consider using std::tuple instead of structs. You could then use various template facilities to work through the members of the tuple.
Here is a simple example that prints the elements of a tuple - using boost::fusion::tuple instead of the std::tuple since it has many more tuple-manipulating facilities available:
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>
struct Printer {
template<typename T>
void operator()(const T &t) const {
std::cout << t << std::endl;
}
};
int main(int argc, const char * argv[])
{
boost::fusion::tuple<int, int, int, int, float> t =
boost::fusion::make_tuple(3, 5, 1, 9, 7.6f);
boost::fusion::for_each(t, Printer());
return 0;
}
You could include these in unions with the struct but you'd want to do some testing to ensure proper alignment agreement.
The upside is that these manipulations are very fast - most of the work is done at compile time. The down-side is that you can't use normal control structs like indexing with runtime indices - you'd have to build an abstraction layer around that as the normal get<i>(tuple) accessor requires that i be a compile time constant. Whether this is worth the complexity depends strongly on the application.

How about:
vector <Foo> Bar;
You can then add instances of your struct and then access each element as desired, using an array-like format.
See this related question for further information:
Vector of structs initialization
Upon re-reading your question a few times, I think I mis-understood your intent and answered the "wrong question". You can make an array of your struct as mentioned above and index it as an array, but I don't believe it is quite as simple as that to make each struct element a different element of an array. If you are looking to make an array of structs, my answer should help. If you are looking to make each element of your struct an element of your array, 40two's answer should help you out.

Related

How to make a class with 'dynamic' data types?

In the C++ standard library, there is std::vector, and you can specify the type you want to put into a vector while declaring it.
I want to create a class which would contain a vector of either strings, or ints, or whatever I would ever need. Is it possible to do this in an easy way, or would I have to write thousands of lines in C and assembly?
If you put the data type in the declaration, you can instantiate different kinds of vectors: vector<int> myint_v; vector<string> mystring_v; etc.... but I think your asking about how to make a Generic class and GeeksForGeeks has a really good article on this.
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T* ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
template <typename T>
Array<T>::Array(T arr[], int s)
{
ptr = new T[s];
size = s;
for (int i = 0; i < size; i++)
ptr[i] = arr[i];
}
template <typename T>
void Array<T>::print()
{
for (int i = 0; i < size; i++)
cout << " " << *(ptr + i);
cout << endl;
}
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
Array<int> a(arr, 5);
a.print();
return 0;
}
That's just an example of using a template to declare a methods in a class. Hopefully that helps. Let me know.
C++ has variant and any. Variant supports a fixed list of alternative types; any supports any type of object that can be copied.
Now, any is really tricky to use right; in order to get back your data, you have to know what type of data (exactly) is in the any. And often variant is all you need.
If your goal is something akin to a json structure, well there are plenty of implementations of that.
Yes you can do via some sort of manipulation. Easiest method so far i have would be using std::pair<type1,type2> method. I will initiliaze with string and double which would be able to hold most of the things you need. String can hold single character to whole text and double pretty much same thing for the number.
Easiest way is,
vector<pair<type1,type2>> vector_name;
Then push each value via make_pair method
vector_name.push_back(make_pair(type1 Value, type2 Value));
When accessing it .first is for type1 and .second would be for type2. You can see more in the code below
#include <iostream>
#include <vector>
#include <utility>
#include <string>
using namespace std;
int main(){
vector<pair<string, double>> mypair;
mypair.push_back(make_pair("HelloWorld!", 8.2021));
mypair.push_back(make_pair("!", 8));
for(auto &&i:mypair){
cout << i.first << " " << i.second << "\n";
}
return 0;
}
I want to add a major difference. std::variant is a compile time feature where std::any is runtime.
Generally, what you want is std::any. Variant is a type safe union which somehow breaks what the original union was designed for (to overlook types at runtime as well).
The benefit of std::any is that your don't have to change often a type which can contain a std::any instead of constantly changing the data (and, for example, to recompile the entire precompilation headers). The drawback is that you have to ensure that it contains the type you want, or you get an exception when using std::any_cast. There is added overhead as well.
The final advice is to avoid using any of the two, unless there is a good reason. There are safer ways to use multiple types (polymorphism). As said, your can also put your data inside an object like json or XML.

Adding Iterable Element to Struct With Mixed Struct Element Types

EDIT
I am coding in c++11.
I have programs that I write for micro controllers that use a struct to store items in flash memory together. For example
struct save{
char name[10]="bob";
int weight=244;
char food[50]="Taco";
} myVals;
I know that there is no built in way to iterate through struct values, but I figure I should be able to add some sort of container with reference to the struct values, but figuring out one that can take different types has been challenging for me. The best I've been able to do so far is a function to print them out, like below.
struct save{
char name[10]="bob";
int weight=244;
char food[50]="Taco";
function dump(){
printf("{\"name\":\"%s\",\"weight\":%s,\"food\":\"%s\"}",name,weight,food);
}
} myVals;
However, what I really want is an object I can iterate through. I realize there is no reflection in C++, but is there a way I can build it in to my struct? Is there a way to create some container like this where I just give it a list of types and a list of items?
mylist<char* ,int, char*> {name,weight,food}
EDIT
I tried using a tuple. I cannot use it inside the struct.
struct Data{
char name[10]="bob";
int weight=14;
char food[50]="taco";
int size=3;
tuple<char*,int,char*> mylist (name,weight,food);
} data;
becuase I get errors like
error: ‘name’ is not a type
However, if I put it outside the struct it compiles and I can get values.
struct Data{
char name[10]="bob";
int weight=14;
char food[50]="taco";
int size=3;
} data;
tuple<char*,int,char*> mylist (data.name,data.weight,data.food);
int main(){
printf("%s",get<0>(mylist));
return 0;
}
>food
Unfortunately this doesn't really help as tuples are notoriously hard to iterate over.

Structs - expression must be a modifiable value

I'm new to structs and I'm struggling a bit.
I have the following struct:
typedef struct
{
CHAR_t bWpId[10];
CHAR_t bWpDescr[25];
UINT16_t wCoA;
sUtmCoordinate_t Coordinate;
} sWaypoint_t;
typedef struct
{
sWaypointListElement Element[cMAX_WAYPOINTS];
UINT8_t bHead;
UINT8_t bTail;
UINT8_t bNumElements;
} sWaypointList;
Now each waypoint is an element in a waypointlist which is also a struct.
class CWaypointList
{
private:
sWaypointList WaypointList;
}
Now my question is how do I read in values in each element of the struct without writing accessors? Is accessors the only way to access the data within a private struct?
If I do it like this I get the error : expression must be a modifiable value.:
element.bWpId = {'0','0','0','0','0','0','0','0','0','1'};
You can't use that syntax to initialize an array outside of the arrays definition. You have to fill in all values manually.
Fortunately there are standard C++ functions to do that for use, like std::fill:
std::fill(std::begin(element.bWpId), std::end(element.bWpId), '0');
element.bWpId[9] = '1';
You can of course make a constructor for the sWaypoint_t structure, and initialize the array in that:
typedef struct sWaypoint_s
{
CHAR_t bWpId[10];
CHAR_t bWpDescr[25];
UINT16_t wCoA;
sUtmCoordinate_t Coordinate;
sWaypoint_s()
: bWpId{'0','0','0','0','0','0','0','0','0','1'}
{}
} sWaypoint_t;
The problem with this is that it requires a C++11 capable compiler.
In C++ you can not list-initialise array that has already been constructed. Same applies for list-initialising structures.
Using std::fill is one way, but I dislike its obscurity. Instead you can try using this helper function:
template <class T, size_t Size>
void copy_array(T (&dst)[Size], const T (&src)[Size])
{
std::copy(src, src+Size, dst);
}
Now you can "assign" any array. In the case of element.bWpId:
CHAR_t temp[] = {'0','0','0','0','0','0','0','0','0','1'};
copy_array(element.bWpId, temp);
The function will compile-time check arrays types and sizes, so it leaves no opportunity for a mistake. Which is a huge advantage over explicit std::fill and manual indexing.
All that provided you don't have access to C++11 compiler. If you have, just change the bWpId to std::array<Char_t, 10> and then you can list-initialise it anytime you want.
I used sprintf(element.bId,'0');

C++ macro/metaprogram to determine number of members at compile time

I am working on an application with a message based / asynchronous agent-like architecture.
There will be a few dozen distinct message types, each represented by C++ types.
class message_a
{
long long identifier;
double some_value;
class something_else;
...//many more data members
}
Is it possible to write a macro/meta-program that would allow calculating the number of data members within the class at compile time?
//eg:
class message_b
{
long long identifier;
char foobar;
}
bitset<message_b::count_members> thebits;
I am not familiar with C++ meta programming, but could boost::mpl::vector allow me to accomplish this type of calculation?
as others already suggested, you need Boost.Fusion and its BOOST_FUSION_DEFINE_STRUCT. You'll need to define your struct once using unused but simple syntax. As result you receive required count_members (usually named as size) and much more flexibility than just that.
Your examples:
Definition:
BOOST_FUSION_DEFINE_STRUCT(
(), message_a,
(long long, identifier),
(double, some_value)
)
usage:
message_a a;
size_t count_members = message_a::size;
No, there is no way in C++ to know the names of all members or how many members are actually there.
You could store all types in a mpl::vector along in your classes but then you face the problem of how to turn them into members with appropriate names (which you cannot achieve without some macro hackery).
Using std::tuple instead of PODs is a solution that generally works but makes for incredible messy code when you actually work with the tuple (no named variables) unless you convert it at some point or have a wrapper that forwards accessors onto the tuple member.
class message {
public:
// ctors
const int& foo() const { return std::get<0>(data); }
// continue boiler plate with const overloads etc
static std::size_t nun_members() { return std::tuple_size<data>::value; }
private:
std::tuple<int, long long, foo> data;
};
A solution with Boost.PP and MPL:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/at.hpp>
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
struct Foo {
typedef boost::mpl::vector<int, double, long long> types;
// corresponding type names here
#define SEQ (foo)(bar)(baz)
#define MACRO(r, data, i, elem) boost::mpl::at< types, boost::mpl::int_<i> >::type elem;
BOOST_PP_SEQ_FOR_EACH_I(MACRO, 0, SEQ)
};
int main() {
Foo a;
a.foo;
}
I didn't test it so there could be bugs.
There are several answers simply saying that it is not possible, and if you hadn't linked to magic_get I would've agreed with them. But magic_get shows, to my amazement, that it actually is possible in some cases. This goes to show that proving that something is not possible is harder than proving that something is possible!
The short answer to your question would be to use the facilities in magic_get directly rather than reimplement them yourself. After all, even looking at the pre-Boost version of the code, it's not exactly clear how it works. At one point in the comments it mentions something about constructor arguments; I suspect this is the key, because it is possible to count the arguments to a regular function, so perhaps it is counting the number of arguments needed to brace-initialise the struct. This indicates that it may only be possible with plain old structs rather than objects with your own methods.
Despite all this, I would suggest using a reflection library as others have suggested. A good one that I often recommend is Google's protobuf library, which has reflection and serialisation along with multi-language support. However, it is intended only for data-only objects (like plain old structs but with vectors and strings).
Plain structs do not support counting members, but boost::fusion offers a good way to declare a struct that is count- and iteratable.
Something like this might get you closer:
struct Foo {
Foo() : a(boost::get<0>(values)), b(boost::get<1>(values)) {}
int &a;
float &b;
typedef boost::tuple<int,float> values_t;
values_t values;
};
If your types respect some properties ("SimpleAggregate"), you might use magic_get (which is now boost_pfr) (from C++14/C++17).
So you will have something like:
class message_b
{
public;
long long identifier;
char foobar;
};
static_assert(boost::pfr::tuple_size<message_b>::value == 2);

C++ initialization of struct containing an array

I have a structure that more or less follows this pattern:
struct sTruct {
int count;
struct {
int A;
int B;
int C;
} array[]; //count is the size of this array
};
I would like to be able to initialize these with something like the following syntax:
sTruct gInit1 = { 2, { {1,2,3},{4,5,6} }};
Really, that initialization syntax (or rather, the compactness of it) is more important than the specific struct layout. I do not have access to the standard containers (embedded platform), but I might be able to replicate some of their behavior if needed.
In final form, I would like to initialize an array of roughly 300 of these sTruct containers at once, just to add one more level of parenthesis.
You can't do it. If you gave the array a size you could. An alternative might be:
template < int size >
struct sTruct
{
struct { int a, int b, int c } array[size];
};
sTruct<2> gInit1 = {{1,2,3},{4,5,6}};
But, of course, all your sTructs are different types and so it may not be what you want. Your only other alternative is going to have to be free-store based and won't give you that syntax until initialization lists in 0x.