Вызов автоматического конструктора: почему мой тип неполон? - PullRequest
3 голосов
/ 13 марта 2019

В следующем коде я хочу использовать конструктор по умолчанию {.data = value}, потому что я хочу, чтобы мой класс был POD. Я не понимаю сообщение об ошибке при компиляции (llvm или 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;
}

с сообщением об ошибке

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 &'

Может ли какая-то добрая душа объяснить мне, почему тип а неполный, когда я хочу его использовать, и почему он рассматривается как void?

1 Ответ

2 голосов
/ 13 марта 2019

Вы не можете агрегировать инициализировать частного участника.

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

Агрегат - это один из следующих типов: ... тип класса (обычно структура или объединение), который не имеет закрытых или защищенных нестатических элементов данных

Поскольку a является class, а не struct, data является private.

Объявите data как public, или объявите тип как struct, чтобы установить по умолчанию public.

Затем заменить static inline a create(char c) { return {.data = c}; }

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

за https://en.cppreference.com/w/cpp/language/list_initialization

прямая инициализация списка (2)

...