7

I was was wondering if anyone knows if it's possible to use inheritance within a union somehow.

In the example below, the TestFails union will not contain the a variable within the Base struct, while TestWorks does work.

struct Base { int a; };

union TestFails
{
    struct : public Base {};
    int b;
};

union TestWorks
{
    struct  { int a; };
    int b;
};

int main()
{
    TestWorks works;
    works.a = 0;

    TestFails fails;
    fails.a = 0;

    return 0;
}

You can test the code here: http://ideone.com/dUzpOR

AndyG
  • 39,700
  • 8
  • 109
  • 143
Artoo
  • 116
  • 7
  • Out of curiousity, why do you want this? – Cameron Dec 03 '15 at 20:34
  • I have a few unions which need some tidying up, which contents are quite similar, so I was hoping to have some base data structs which I could re-use. – Artoo Dec 03 '15 at 20:36
  • FWIW, this appears to not be specific to unions: http://ideone.com/9VGAkz – user253751 Dec 03 '15 at 20:43
  • 1
    Seems this is unrelated to unions. What you're really after is transparent/unnamed/anonymous (I can't find a standard name for this) structure inheritance in general. It [works when you name the struct](http://ideone.com/JNnW3R). – Cameron Dec 03 '15 at 20:47
  • That would work, but it is what I'd like to avoid to make this change transparent to the rest of my code. – Artoo Dec 03 '15 at 20:50
  • @Beyeler: Even if it was, though, it would mostly defeat the purpose if you had to name every member from the base each time you inherited. – Cameron Dec 03 '15 at 21:07
  • @Artoo: What about some hack where you allow implicit conversion between `Base` and the types in question? Something gross like this: http://ideone.com/1w5idq – AndyG Dec 03 '15 at 21:11
  • @BeyelerStudios: Because unnamed structs are *not standard* in C++. (Edit: changed illegal to "not standard") – AndyG Dec 03 '15 at 21:11
  • @Artoo (and I should note that the linked code only uses inheritance because you asked for it, the same soln would work with just `Base`) – AndyG Dec 03 '15 at 21:14
  • @AndyG That would work just if the base class would contain a single element of a given data type. And I also think it's quite "gross" XD – Artoo Dec 03 '15 at 21:26

3 Answers3

1

First of all - your assumption that TestWorksworks is wrong. This is not standard C++ - only extension to it - it is called unnamed anonymous struct - and when you compile with pedantic options you get:

prog.cc:5:27: error: ISO C++ prohibits anonymous structs [-Wpedantic]
struct : public Base {};

                       ^

prog.cc:11:22: error: ISO C++ prohibits anonymous structs [-Wpedantic]
struct { int a; };

To solve your issue - just name these anonymous structs:

union TestFails
{
    struct : public Base {} s;
    //                      ^
    int b;
};

union TestWorks
{
    struct  { int a; } s;
    //                 ^
    int b;
};
Community
  • 1
  • 1
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • I knew anonymous structs are not standard, but that's exactly what I was trying to avoid as per my comment above. Thanks for your help anyway. – Artoo Dec 03 '15 at 21:17
1

The answer is no. There are a lot of dark corners in c++ but this is not one them :)

classes and structs have inheritance. unions do not.

The only way to accomplish what you are trying... is refactor your unions to structs (I say structs only because they have a default public scope, so you don't need to declare them public)

If you try to place a struct inside your union you will need add the extra scope of the new struct in order to access its value.

Exactly as AndyG's answer shows this:

union TestFails
{
    struct foo: public Base {};
    foo f;
    int b;
};

TestFails fails;
fails.f.a = 42;
std::cout << fails.f.a << std::endl;

If you omit a variable named and create an unnamed scope which is done with namespaces occasionally then the data can not be accessed externally (which is the point of this in the first place)

Dan
  • 1,096
  • 9
  • 13
  • Unions inheritance is not under discussion here, the inheritance affects a struct within a union, which is a completely different issue as far as I am aware. Can you please extend your solution using namespaces? – Artoo Dec 03 '15 at 21:28
  • 1
    I understand that union inheritance is not your question, but the only way to accomplish your goal is inheritance. By refactoring into a struct you will be able to access the value 1 level deep in your union so that you are only accessing the value as `f.a` instead of `f.s.a`. This conforms to the `is a` relationship vs the `has a` relationship that you are approaching from currently – Dan Dec 03 '15 at 21:41
  • The point about unnamed namespaces just goes along with anything else anonymous/unnamed. They are not meant to be accessed externally or they are temporary. – Dan Dec 03 '15 at 21:44
0

Not sure if it helps, but this works:

struct Base { int a; };
struct Foo : Base { int b;};
union TestFailsNot {
    Base base;
    Foo foo;
    int b;
};

int main() {
    TestFailsNot failsNot;
    failsNot.foo.a = 0;    
    failsNot.base.a = 3; // maybe not what you want to do, but it works
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185