Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling automatic constructor: why is my type incomplete?

In the following code, I want to use the default constructor {.data = value}, because I want my class to be POD. I don't understand the error message I get on compilation (llvm or gnu, c++11):

#include <type_traits>

class a {
  char data;
  static inline a create(char c) { return {.data = c}; } // this fails
  static inline a create2(char c) { a x; x.data = c; return x; } // this is OK
public:
  void init(char c) { *this = create(c); }
};

int main() {
  a s;
  s.init('x');
  return std::is_pod<a>::value;
}

with error message

t.cc:5:43: error: no matching constructor for initialization of 'a'
  static inline a create(char c) { return {.data = c}; }
                                          ^~~~~~~~~~~
t.cc:3:7: note: candidate constructor (the implicit copy constructor) not viable: cannot convert
      argument of incomplete type 'void' to 'const a &'

Can some kind soul explain to me why the type of a is incomplete when I want to use it, and why it's treated as void?

like image 334
grok Avatar asked Mar 17 '26 18:03

grok


1 Answers

You cannot aggregate initialize a private member.

From https://en.cppreference.com/w/cpp/language/aggregate_initialization

An aggregate is one of the following types: ... class type (typically, struct or union), that has no private or protected non-static data members

Since a is a class, not a struct, data is private.

Declare data to be public, or declare the type to be a struct to default it to public.

Then replace static inline a create(char c) { return {.data = c}; }

with static inline a create(char c) { return a { c }; }

per https://en.cppreference.com/w/cpp/language/list_initialization

direct-list-initialization (2)

like image 155
Tzalumen Avatar answered Mar 20 '26 11:03

Tzalumen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!