Union

Hi

I keep getting the message in the compiler:
Unknown Type Name for every object in my union:

#ifndef UnionBase_hpp
#define UnionBase_hpp

#include <stdio.h>
#include "BaseEntity.hpp"
#include "Entity.hpp"
#include "EmptyPawn.hpp"
#include "WeaponEntity.hpp"
#include "WalkingEntity.hpp"
#include "IntelligentEntity.hpp"
#include "PlayerCharacter.hpp"
#include "StaticMesh.hpp"

/* class votes to be the one to be picked*/
union union_base {
BaseEntity baseEntity;
Entity entity;
EmptyPawn emptyPawn;
WeaponEntity weapon;
WalkingEntity walkingEntity;
IntelligentEntity intelligentEntity;
PlayerCharacter playerCharacter;
StaticMesh staticMesh;


};
The compiler doesn't know what a BaseEntity object (or any of the others) is.

Which I'd guess means that something has gone wrong with your include files.

Here's a working example: https://ideone.com/WdLfle
Remove any class definition and watch the same error you're experiencing appear.
Last edited on
While I'm here:
#include <stdio.h>
That's a bad sign.

In C++ we use <cstdio> instead, and we don't ever like to do that; what do you need from that header that you can't do better with C++?

Also, union. That's a bad sign too. This looks like you're implementing polymorphism yourself, manually. C++ does that for you if you just work with it.
I"m having all kinds of problems with my include files.
Any suggestions on how to straighten them out?
Well, I haven't seen them, but typical good advice is simplify them.

Get this working first:

1
2
3
4
5
6
#include "BaseEntity.hpp"

union union_base 
{
BaseEntity baseEntity;
}; 
I'm having all kinds of problems with my include files. Any suggestions on how to straighten them out?

Some suggestions:
> Only include header files.
> Every header file must include a unique header guard.
> Do not rely on transitive or indirect inclusions: include exactly the files you need on a file-by-file basis.
> Factor out code to eliminate cyclical dependencies (e.g., a.hpp depends on b.hpp depends on a.hpp), if any exist.
> If a source file has a corresponding header, include the corresponding header file first in the source file.
> Split your code up in the way that best supports your project's physical and logical structure. In particular, you need not place one class per file.
> Not every entity ought to be defined in a header file (or have external linkage). If a component isn't required elsewhere, give it internal linkage and define it in the source file.

Last edited on
Ok. I have this working:



#ifndef BaseEntity_hpp
#define BaseEntity_hpp

#include <stdio.h>
//#include "SceneGraphNode.hpp"
#include "UnionBase.hpp"
#include "Message.hpp"




class BaseEntity //: public SceneGraphNode
{
public:
void dispatch(Message *msg); //see message manager for instructions
//class entity is the foundation of messenger
//dispatch processes in the Finite State Machine
void notify(); //notifies the dynamic BSP that a change occurred to
//the mesh and it has to rebalance
//in this case you can use FLINCH in place of the plain vanilla finite state machine

int owner_index; //identity for message
union union_base union_joined;


except for the union that just says "Field has incomplete type union union_base"

OK let's scrap the union idea. I wasn't too fond of it anyway.
This is the problem I have got to solve.

I have a class called Advisor which has two members, a Message class message and a BaseEntity class called event.
THe BaseEntity class has an inheritance tree going from Entity Class to Intelligent Class to PlayerCharacter at the most. Each of the entity classes h as its own finite state machine in it. My problem is storing the entity class. I need to have any one of the entity classes in the Advisor's event member variable.
> My problem is storing the entity class. I need to have any one of the entity classes
> in the Advisor's event member variable.

Use a reference (the event object is always present and it is the same object throughout).

If that is not feasible (the event object is always present but may be a different object at different points in time), use a wrapped reference.
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

If that too is not feasible (there may be cases/times where there is no event object at all), use a pointer.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <typeinfo>
#include <functional>

struct base_entity { virtual ~base_entity() = default ; /* ... */ };

namespace plain_reference
{
    struct advisor
    {
        explicit advisor( base_entity& be ) noexcept : event(be) {}

        virtual const char* event_type() const noexcept { return typeid(event).name() ; }

        base_entity& event ; // reference: the dynamic type of the object referred to
                             // can be any of the (publicly) derived classes of base_entity
        // ...
    };
}

namespace wrapped_reference
{
    struct advisor
    {
        explicit advisor( base_entity& be ) noexcept : event(be) {}

        virtual const char* event_type() const noexcept { return typeid( event.get() ).name() ; }

        std::reference_wrapper<base_entity> event ; // assignable reference: the dynamic type of the object referred to
                                                    // can be any of the (publicly) derived classes of base_entity
        // ...
    };
}

namespace pointer // non-owning
{
    struct advisor
    {
        explicit advisor( base_entity* be ) noexcept : event(be) {}

        virtual const char* event_type() const noexcept
        {
            if(event) return typeid( *event ).name() ;
            else return "there is no event object" ;
        }

        base_entity* event ; // nullable pointer: the dynamic type of the object pointed to
                             // can be any of the (publicly) derived classes of base_entity
        // ...
    };
}

struct intelligent_entity : base_entity { /* ... */ };
struct player_character : base_entity { /* ... */ };

int main()
{
    intelligent_entity a, b ;
    player_character c, d ;

    {
        using namespace plain_reference ;
        std::cout << "\nplain_reference\n--------\n" ;
        const advisor advisors[] = { advisor(a), advisor(b), advisor(c), advisor(d) } ;
        for( const advisor& adv : advisors ) std::cout << adv.event_type() << '\n' ;
    }

    {
        using namespace wrapped_reference ;
        std::cout << "\nwrapped_reference\n--------\n" ;
        advisor advisors[] = { advisor(a), advisor(b), advisor(c), advisor(d) } ;
        for( const advisor& adv : advisors ) std::cout << adv.event_type() << '\n' ;

        std::cout << '\n' ;
        // replace the referred objects
        advisors[1].event = d ;
        advisors[3].event = b ;
        for( const advisor& adv : advisors ) std::cout << adv.event_type() << '\n' ;
    }

    {
        using namespace pointer ;
        std::cout << "\npointer\n--------\n" ;
        advisor advisors[] = { advisor(&a), advisor(&b), advisor(&c), advisor(&d) } ;
        for( const advisor& adv : advisors ) std::cout << adv.event_type() << '\n' ;

        std::cout << '\n' ;
        advisors[1].event = &d ; // point to a different object
        advisors[3].event = nullptr ; // remove the event object
        for( const advisor& adv : advisors ) std::cout << adv.event_type() << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/27523e6548ca31fe
https://rextester.com/RTH84614
unions are sort of C-ish. With the ban on the union hack (its been deemed undefined behavior), I have not seen a lot of use for them in c++. Basically the only thing they were good at was killed. Its probably best if you avoid them.

If you want a C++ type safe version of union, the ability at any given time to hold a value of one of its alternative types, use std::variant.

https://en.cppreference.com/w/cpp/utility/variant

Requires C++17 or later to use.

I don't recommend using it, since you are trying to work out the intricacies of class inheritance.

https://www.learncpp.com/cpp-tutorial/111-introduction-to-inheritance/
Last edited on
Topic archived. No new replies allowed.