3

I have a bunch of simple structures inherited from some interface, and I cannot use list initialization for them:

https://godbolt.org/z/PWjPzK

#include <iostream>
#include <string>

class Foo
{
public:
  virtual void write() = 0;
};

struct Bar : public Foo // if I remove this inheritance, it will compile
{
  int num;
  void write()
  {
    std::cout << "num = " << num;
  }
};

int main()
{
    Bar b{ 11 }; // error here
    b.write();
    return 0;
}

Edit: compiler outputs with several warnings and error:

<source>:21:15: error: no matching function for call to 'Bar::Bar(<brace-enclosed initializer list>)'
   21 |     Bar b{ 11 };
      |               ^
<source>:10:8: note: candidate: 'Bar::Bar()'
   10 | struct Bar : public Foo // if I remove this inheritance, it will compile
      |        ^~~
<source>:10:8: note:   candidate expects 0 arguments, 1 provided
<source>:10:8: note: candidate: 'constexpr Bar::Bar(const Bar&)'
<source>:10:8: note:   no known conversion for argument 1 from 'int' to 'const Bar&'
<source>:10:8: note: candidate: 'constexpr Bar::Bar(Bar&&)'
<source>:10:8: note:   no known conversion for argument 1 from 'int' to 'Bar&&'

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Sairus
  • 384
  • 1
  • 15

1 Answers1

2

The structure Bar is not an aggregate because it has a virtual function.

From the C++ 17 Standard (11.6.1 Aggregates)

1 An aggregate is an array or a class (Clause 12) with

...

(1.3) — no virtual functions (13.3), and

So you may not initialize an object of the structure type as an aggregate.

On the other hand, the structure does not have a constructor with a parameter.

So the compiler issues an error for this declaration

Bar b{ 11 };
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335