0

I am trying to use struct initialization on a derived from template struct. The code goes something like this:

template <class Derived>
struct Event{
//the level of access on the ctor has nothing to do with the problem
//protected:
//    Event() = default;
};

struct MoveEvent: Event<MoveEvent>{
    int x, y;
};


int main(){
    //how do I make this work?
  //MoveEvent event = {.x =5, .y = 4};
}

I thought it might have something to do with CTRP, but changing Event<MoveEvent> to Event<int> yields the same problem. Furthermore, I thought it was an issue with POD, but std::is_pod returns true for MoveEvent. So what's the problem here? Why can't I use struct initialization?

user975989
  • 2,578
  • 1
  • 20
  • 38

2 Answers2

6

You can only do aggregate initialization on aggregates. An aggregate is, from [dcl.init.aggr]:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

MoveEvent is not an aggregate. Thus, you will have to add a constructor:

template <class Derived>
struct Event {
};

struct MoveEvent: Event<MoveEvent> {
    MoveEvent(int x, int y) : x(x), y(y) { }
    int x, y;
};


int main() {
    MoveEvent event{5, 4}; // NOW this is fine
}
Barry
  • 286,269
  • 29
  • 621
  • 977
3

You cannot use this syntax for a couple reasons, firstly that "designated initializers" are a C feature, not a C++ feature

MoveEvent event = {.x = 5, .y = 4};

Secondly, you cannot use aggregate initialization for a derived class, because as soon as you introduce inheritance, you no longer have a POD aggregate type.

Your best best is to define a constructor for the derived class

struct MoveEvent: Event<MoveEvent>
{
    MoveEvent(int _x, int _y) : x{_x}, y{_y} {}
    int x, y;
};

Then you can do this

MoveEvent event{5, 4};
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218