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
Related
I'm trying to figure out the way to cast two types that have the same fields but in a different order (or even some of them missing) without copying.
For example, if we have the following structures:
typedef struct Foo {
int age;
float height;
char* name;
} Foo;
typedef struct Bar {
float height;
float weight;
char* name;
int age;
} Bar;
Is there any way to cast Bar into Foo without having to make an intermediate copy?
Bar bar;
Foo foo;
bar = foo;
Moreover, would it be possible to do it with a pointer cast?
Bar *bar;
Foo foo;
bar = &foo
Thanks in advance!
Regards,
Salva
No.
Those are unrelated types.
You can either copy the data from the first object into the second or, in some limited cases, use some pointer magic to pretend that the first object has the type of the second. This is not one of those cases.
Fortunately, copying ints and floats is cheap and depending on your circumstances may not actually involve any activities at runtime (compilers are smart!).
Not directly like that. You cannot make a pointer of a type point to a unrelated type, this would be a violation of the aliasing rule.
You could do that with a union if both type had a common initial sequence. However, you do not have that: some of the first members are not the same types.
Here's an example of your structs with the common initial sequence:
struct Foo {
char const* name;
int age;
float height;
};
struct Bar {
char const* name;
int age;
float height;
float weight;
};
union Foobar {
Foo foo;
Bar bar;
};
auto const foobar = Foobar{Bar{}};
// can access foo even though bar is initialized.
// a whole foo is a common initial sequence of bar.
Foo const* foo = foobar.foo;
You could also simply put the common member in a parent class:
struct common {
char const* name;
int age;
float height;
};
struct Foo : common {
// whatever
};
struct Bar : common {
// whatever
};
I'm fairly new to c++, and am trying to create a const pointer array to hold shortcuts to a few structures.
The issue I'm having is that C++03 (or the compiler I'm using - gcc 4.4.7) apparently doesn't support constant pointer arrays? Or at least you can't create them for existing objects?
To clarify, the pointers themselves are to be constant, but the objects they point to are variable. And the array structure is crucial because it greatly simplifies my code if I can access these objects by index later on.
This is for work with spacecraft hardware that has flight heritage or something, so it's not feasible to use a newer compiler :/
struct Type1 {
unsigned short thing1;
};
struct Type2 {
Type1 thing2;
};
struct Type3 {
Type2 thing3;
};
class A {
Type3 Array[4];
Type1 *const pArray[4] = {
&Array[0].thing3.thing2,
&Array[1].thing3.thing2,
&Array[2].thing3.thing2,
&Array[3].thing3.thing2
};
};
error: a brace-enclosed initializer is not allowed here before ‘{’ token
error: ISO C++ forbids initialization of member ‘pArray’
error: making ‘pArray’ static
error: invalid in-class initialization of static data member of non-integral type ‘MyType* const [4]’
So is it even possible to do what I'm trying to do given the compiler I'm using?
Because pArray is const, it requires an initializer. Because it is a non-static member variable, it can only be initialized from the initializer list of a constructor. Because it is an array, there is no syntax for this in C++03.
One possible workaround is to make it a non-array:
#include <cstddef>
struct Type1 {
unsigned short thing1;
};
struct Type2 {
Type1 thing2;
};
struct Type3 {
Type2 thing3;
};
class A {
struct xarray4 {
Type1 *data[4];
xarray4(Type1 *p0, Type1 *p1, Type1 *p2, Type1 *p3) {
data[0] = p0;
data[1] = p1;
data[2] = p2;
data[3] = p3;
}
Type1 *&operator[](std::size_t n) {
return data[n];
}
Type1 *const &operator[](std::size_t n) const {
return data[n];
}
};
Type3 Array[4];
const xarray4 pArray;
A() : pArray(
&Array[0].thing3.thing2,
&Array[1].thing3.thing2,
&Array[2].thing3.thing2,
&Array[3].thing3.thing2
) {
}
};
Here pArray is not an array, but an object with overloaded operator[]. Because it is an object, we can give it a custom constructor that lets us initialize it the way we want.
With the overloaded [] operator we can still access the pointers by index.
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;
};
I have problem with this code,this is a header file(stack.h) from a maze program. i was studying Stack structure, and in my documents, i couldn't understand these type of structures, can anyone explain to me why we are using typedef and how the 12th and 21st line works??
#ifndef STACK_H
#define STACK_H
#define STACKSIZE 50
typedef struct d {
int x;
int y;
int right; int left;
int down;
int up;
int camefrom;
} StackDataType, position; /// LINE 12
struct STACK{
StackDataType element[STACKSIZE]; int top;
void create();
void close();
bool push(StackDataType); StackDataType pop();
bool isempty();
};
typedef struct STACK Stack; /// LINE 21
#endif
I think you do not need to typedef a struct again in C++, it again defines a struct, which is unnecessary. You can just define:
struct d{
};
In my (considerable) experience, this almost always denotes a C programmer who has fumbled their way into C++. If these are notes from your classes, it doesn't bode well.
In the earliest "C", if you declared a struct
struct StructName {
int a;
int b;
};
This didn't declare a type name, it only declared a struct name, so to make an instance of StructName you would have to write:
struct StructName myStruct;
If you wanted to be able to omit the "StructName" part you would need to use a typedef:
struct StructName { int a, b; };
typedef struct StructName StructName;
Or you could combine these into one, somewhat confusing, statement:
typedef struct StructName { int a, b; } StructName;
I say confusing because if the struct definition is many lines long, it could be confused for a second C syntax which lets you declare an instance of a Struct after defining the type:
struct StructName { int a, b; } StructName;
// aka
struct StructName { int a, b; };
struct StructName StructName; // local variable, StructName of type struct StructName
// declare a VARIABLE called StructName which is of type anonymous-struct.
struct { int a, b; } StructName;
One problem with this is that you can't use the typedef'd name in the structure declaration:
// Won't compile because 'List' isn't declared until the end.
typedef struct list_structure { List* next; int a; } List;
// Won't compile because you have to remember to say 'struct List'
typedef struct List { List* next; int a; } List;
// Compiles
typedef struct list_structure { struct list_structure* next; int a; } List;
This confused a lot of C programmers. Enough so that many C programmers will tell you that the definition of a struct is
typedef struct tag_name { /* struct details */ } structname;
//e.g.
typedef struct tagStructName { int a, b; } StructName;
C++ inherited all of this, but also went ahead and made the typedef implied for you:
// doesn't compile as C, will compile as C++
struct List {
List* next;
int a;
};
To see it not compiling as C: http://ideone.com/3r9TRy
In C++, declaring something as a class is exactly the same as declaring it a struct, with one change:
class List {
List* next;
public:
int a;
};
Is EXACTLY as though you had written:
struct List {
private:
List* next;
public:
int a;
};
There's no other difference between a struct and a class in C++.
I can see two problems: The first is the mysterious symbol  in the definition of the d structure. The second is that you use typedef for that structure too, but have something after the typename StackDataType. The second error you get is probably just because of the first one, it's very common in C and C++ to get errors in unrelated lines because of previous errors.
Besides, in C++ you don't really need typedef for structures, as they are the same as classes so doing e.g. struct StackDataType {...}; will allow you to use StackDataType as a type.
What's going on is that essentially the typedef is being used to create a shorthand way to refer to the given structure.
So in this example, both StackDataType and position are shorthand references to what is formally declared as struct d, and Stack is a shorthand reference to what is formally declared as struct STACK.
Generally speaking, this allows for cleaner code referencing these structures. E.g., instead of having to write:
struct STACK var;
to declare an instance of this structure, you can just use:
Stack var;
You can declare a typedef either at the same point at which you declare the type (as in the first example), or you can declare it later (as in the second).
typedef struct
{
int y;
int weight;
struct edgenode * next;
}edgenode;
This code is giving error : 'edgenode' : redefinition; different basic types
It works fine in C code.
Why?
Because your struct doesn't have a name! The question suggests a C heritage - the code is written the way I'd write it.
The pure C++ solution is:
struct edgenode
{
int y;
int weight;
edgenode *next;
};
This will not work in C. In C, and consistent with the question, you would write:
typedef struct edgenode
{
int y;
int weight;
struct edgenode * next;
} edgenode;
Now your struct has a name - struct edgenode. There is also a typedef for it, of course - edgenode, but the compiler doesn't know about that name until it reaches the final semi-colon (approximately). You could also write:
typedef struct edgenode edgenode;
struct edgenode
{
int y;
int weight;
edgenode *next;
};
try:
struct edgenode
{
int y;
int weight;
edgenode* next;
};
In C++ it is no longer required to use the typedef on struct nodes.
Also the way you were using it (for C) was wrong. if you typedef it then there is no need to use struct anymore.
In C you had todo:
// In C:
struct X {};
struct X a;
// C with typedef (Notice here that the struct is anonymous)
// Thus it is only accessible via the typedef (but you could give it a name)
typedef struct {} X;
X a;
// In C++ the use of struct is no longer required when declaring the variable.
struct Y {};
Y a;
No name specified for your struct before you typedef
typedef struct edgenode
{
int y;
int weight;
edgenode* next;
}en;
The difference between C and C++ is, that they treat struct-names and typedef names differently. In C you can not refer to a struct without using the "struct" keyword unless you create typedef name which resolves to the struct name. Therefore this is valid in C, but not in C++:
struct A {};
typedef int A;
int main()
{
A a;
struct A a;
}
structs and typedefs live in a different namespace if you want to. However in C++, both struct and typedef names go into the same namespace. There can be only one A and therefore this example does not compile. So how does this apply to your example? Let's read it the C way:
typedef struct // Here's an unnamed struct
{
int y;
int weight;
struct edgenode * next; // Oh, yes points to some struct called "edgenode" that we don't know of
}edgenode; // and we want to refer to this structs as "edgenode"
This declaration actually created two things called edgenode: A typedef (for the unnamed struct) and an incomplete type "struct edgenode" that is not defined anywhere. You will notice that edgenode x; x.next->y will not compile.
Here's how C++ reads it:
typedef struct // Here's an unnamed struct
{
int y;
int weight;
struct edgenode * next; // Oh, yes points to some struct called "edgenode" that we don't know of
}edgenode; // and we want to refer to this as "edgenode"..HEY WAITASECOND! There's already SOME OTHER THING named edgenode. We know this, because "next" mentioned it!!