1

I encountered a problem when I tried to compile my program on GCC and am interested in knowing how to portably initialize an inherited POD struct using C++11's initializing syntax e.g. struct { int a; int b} my_struct {1, 2}. The problem can be represented minimally with the following code which compiles fine on MSVC.

#include <iostream>

template <typename A>
struct base {
 A a;
};

template <typename A>
class derived : public base<A> {
public:
  derived();
};

template <typename A>
derived<A>::derived() : base {1} {

  std::cout << "Constructed " << a << std::endl;
}

int main() {
  derived<int> d1;
}

However, GCC with C++14 enabled roughly states that derived<A> does not have any field 'base'. So I try the following change.

template <typename A>
derived<A>::derived() : base<A> {1} {

  std::cout << "Constructed " << a << std::endl;
}

GCC now recognizes base<A> as a field of derived<A> fine, but states that a is not declared in this scope.

Funnily enough this change now doesn't compile on MSVC and states "'{': missing function header (old-style formal list?)".

At this point I have no idea how to write this in a standard compliant way.

Thanks.

jezzi23
  • 250
  • 4
  • 12

2 Answers2

0

This makes your last example work:

std::cout << "Constructed " << this->a << std::endl;

Demo: http://coliru.stacked-crooked.com/a/fe9715a447ffbea1

At first I couldn't compile it under MSVC++ 2015 (update 1). After installing update 3 it compiles fine.

zett42
  • 25,437
  • 3
  • 35
  • 72
0

C++17 will support this in some form:

Form aggregate_initialization:

Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

// aggregate
struct base1 { int b1, b2 = 42; };
// non-aggregate
struct base2 {
  base2() : b3(42) {}
  int b3;
};
// aggregate in C++17
struct derived : base1, base2 { int d; };
derived d1{ {1, 2}, { }, 4}; // d1.b1 = 1, d1.b2 = 2,  d1.b3 = 42, d1.d = 4
derived d2{ {    }, { }, 4}; // d2.b1 = 0, d2.b2 = 42, d2.b3 = 42, d2.d = 4

Meanwhile a standard way would be:

template <typename A>
    derived<A>::derived()  {
        this->a = 1;
}
ZivS
  • 2,094
  • 2
  • 27
  • 48