Class that contains a list of itself - c++

This is what I am trying to do (in my header file):
#include <forward_list>
class Data {
public:
Data(int type, union data value);
int which_type();
void set_int(const int& i);
void set_list(std::forward_list<Data*>& l);
int get_int();
std::forward_list<Data*>* get_list();
private:
union data actual_data;
int type;
};
union data {
int i;
std::forward_list<Data*> l;
};
If everything were to work properly, this would create a class which could contain an integer or a list, and it would be as type-safe as possible because I would call the which_type function before every call to one of the get functions, and the get functions would throw an exception if the object isn't the correct type.
However, this isn't possible because Data needs a union data, and union data needs a forward_list<Data*>. I believe boost has what I am looking for, but is there a way to do this without boost? I would just rather use the standard library in order to learn more about the c++ standard library.

All you need is to forward declare the class Data and then declare the union data before the class Data proper declaration.
#include <forward_list>
class Data;
union data {
int i;
std::forward_list<Data*> l;
};
class Data {
public:
Data(int type, union data value);
int which_type();
void set_int(const int& i);
void set_list(std::forward_list<Data*>& l);
int get_int();
std::forward_list<Data*>* get_list();
private:
union data actual_data;
int type;
};
Compiles with g++ and clang++ with no problem.

Class members may not be incomplete class types (although they may be pointers or references to such types). So you need to define union data before you can declare a member of this type in Data. This is straightforward:
class Data {
public:
Data(int type, union data value);
int which_type();
void set_int(const int& i);
void set_list(std::forward_list<Data*>& l);
int get_int();
std::forward_list<Data*>* get_list();
private:
union data {
int i;
std::forward_list<Data*> l;
} actual_data;
int type;
};
Another solution is to define the union first, since it doesn't need the Data class to be complete, since it only uses a pointer to it.
union data {
int i;
std::forward_list<class Data*> l;
};
class Data {
public:
Data(int type, union data value);
int which_type();
void set_int(const int& i);
void set_list(std::forward_list<Data*>& l);
int get_int();
std::forward_list<Data*>* get_list();
private:
data actual_data;
int type;
};

Related

Make struct accept any type insted of float

I'd need to modify a simple struct to accept multiple types of value parameters, as shown below:
struct menuitems_t
{
menuitems_t(std::string name, float* value = 0, int itemtype = menuitemtype::SWITCH)
{
this->name = name;
this->value = value;
this->itemtype = itemtype;
}
std::string name;
float* value;
int itemtype;
};
I tried to create a template from it, but with no luck.
declaring one of these is like menuitems_t(nameString, val1, type);
My only problem is that if I want to use a bool as the referenced value it won't accept it obviously. (I can cast it as a float, but that's not what I want.)
What should I modify in it to accept any types?
You could use a void*, but that's a very C-style and type-unsafe solution to the problem.
Any other pointer can be converted to a void-pointer implicitly, but you need to keep track of the type yourself.
struct menuitems_t
{
std::string name;
void* value;
int itemtype;
};
void foo() {
menuitems_t myItems{"name", nullptr, 0};
// ...
}
On a side note, you don't need a custom constructor and can just use aggregate-initialization.
And it's better practice to use nullptr instead of 0.
Using templates would be more type-safe, but you need to keep track of types at compile-time.
template <typename T>
struct menuitems_t
{
std::string name;
T value; // or T* value if it's still supposed to be a pointer
int itemtype;
};
If there can only be a limited amount of types, you can use a std::variant. You could also just use a union, but unions don't have runtime type-safety like std::variant.
struct menuitems_t
{
std::string name;
std::variant<float, bool> value;
int itemtype;
};

Can a structure with union members be qualified as POD?

Can this structure MyWrapStruct:
struct MyWrapStruct
{
bool myBool;
union
{
struct
{
void* myPtr;
int myInt;
};
Struct1 myStruct1;
Struct2 myStruct2;
} myStructs;
};
With "sub-structures" :
struct Struct1
{
void* myPtr;
int myInt;
float mySpecialFloat;
};
struct Struct2
{
void* myPtr;
int myInt;
int mySpecialInt;
};
Be considered a POD structure?
Yes - even union types merely contains data, and no methods, constructors, etc.
See:
What are POD types in C++?
Update
Provided, of course, the union only contains POD types.
See:
Questions regarding C++ non-POD unions

Access fields in a named union

I want to have a named union in the following struct so that I can memcpy it without knowing what field is "active".
struct Literal {
enum class Type : size_t {
INT = 1,
LONG,
FLOAT,
DOUBLE
} type;
union {
int li;
long ll;
float lf;
double ld;
} v;
constexpr Literal(int li): type{Type::INT}, v.li{li} {}
constexpr Literal(long ll): type{Type::LONG}, v.ll{ll} {}
constexpr Literal(float lf): type{Type::FLOAT}, v.lf{lf} {}
constexpr Literal(double ld): type{Type::DOUBLE}, v.ld{ld} {}
};
How can I initialize the fields in the constructors? Neither v.li{li} nor li{li} are working.
I also tried v{li} but it work only for the first constructor because it cast the 3 others to int.
EDIT: From #StoryTeller answer and comment:
struct Literal {
enum class Type : size_t {
INT = 1,
LONG,
FLOAT,
DOUBLE
} type;
union {
#define UNION_FIELDS int li; long ll; float lf; double ld;
union { UNION_FIELDS } value;
union { UNION_FIELDS };
};
};
You can only initialize direct members of Literal in its c'tors member initializer list. Aggregate initialization of the union member won't work due to narrowing conversions. So your options are to:
Name the union member type, and add appropriate c'tors to it.
Recurse in order to force the union fields into being treated as fields of the Literal class. Have a union of unions, and rely on the common initial sequence guarantee:
union {
union {
int li;
long ll;
float lf;
double ld;
} v;
union {
int li;
long ll;
float lf;
double ld;
};
};
constexpr Literal(int li): type{Type::INT}, li{li} {}
constexpr Literal(long ll): type{Type::LONG}, ll{ll} {}
constexpr Literal(float lf): type{Type::FLOAT}, lf{lf} {}
constexpr Literal(double ld): type{Type::DOUBLE}, ld{ld} {}
The above allows you to refer to each field by name, on account of the anonnymous union member, as well as lumping them together using the named v member. But I'll be the first to admit, it's ugly.

Define dynamic struct

I want to define a structure with different variable type in some field. for example i define a struct like this:
struct sensor {
int index;
int value;
};
struct sensor2 {
int index;
float value;
};
i want to declare only one structure with two option, someone integer value and other time float value, but in unique structure.
My question is :
1.there are anyway to declare one structure and pass parameter to chose one of type (int or float or ...)?
2. can i use template for this reason?
struct sensor {
int index;
type_as_option value; //int or float
};
thank for your aid with best regard
You have several options. You could make it a template:
template <typename T>
struct sensor {
int index;
T value;
};
However, if you want the two structs being the same type, this is not what you are looking for, as
sensor<int>
and
sensor<float>
are two different types.
Second option is (as immibis pointed out in a comment) to simply make a struct with both
struct sensor {
int index;
int ivalue;
float fvalue;
};
However, this introduces almost 50% memory overhead that can be avoided by using a union:
union intOrFloat {
int ivalue;
float fvalue;
};
struct sensor {
int index;
intOrFlaot value;
};
Of the union always only one field is active and it doesnt use more memory than necessary.

How to use anonymous struct or class?

So, it's possible to declalre anonymous class or struct but how to I make it useful?
int main() {
class{
int ClassVal;
};
struct{
short StructVal;
};
StructVal = 5; //StructVal is undefined
ClassVal = 5; //ClassVal is undefined too?
return 0;
}
if you put both of them outside of main function they will be inaccessible as well.
I'm asking this only because it's somehow intersting :)
EDIT:
Why union outside of main function (at global scope) must be static declared
for example:
static struct {
int x;
};
int main() {
//...
}
Anonymous classes and structures may be used to directly define a variable:
int main()
{
class
{
int ClassVal;
} classVar;
struct
{
short StructVal;
} structVar;
structVar.StructVal = 5;
classVar.ClassVal = 5;
return 0;
}
The above is not very common like that, but very common when used in unions as described by Simon Richter in his answer.
These are most useful in the form of nested struct and union:
struct typed_data {
enum type t;
union {
int i; // simple value
struct {
union { // any of these need a length as well
char *cp;
unsigned char *ucp;
wchar_t *wcp;
};
unsigned int len;
};
};
};
Now typed_data is declared as a type with the members t, i, cp, ucp, wcp and len, with minimal storage requirements for its intended use.