Попытайтесь понять сообщение об ошибке компилятора: инициализатор члена по умолчанию требуется до конца его окружающего класса - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь следующий код с тремя компиляторами (msvc2017, gcc8.2, clang7.0) и msvc2017 работает полностью, но gcc и clang нет.Я хочу понять, что не так с моим кодом, и почему компилятор не может его скомпилировать.

#include <cassert>
#include <iostream>
#include <cstdlib>

class Downloader
{
public:

    struct Hints
    {       
        int32_t numOfMaxEasyHandles = 8;
        //Hints(){}          // <= if I uncomment this all works gcc+clang+msvc
        //Hints() = default; // <= if I uncomment this neither clang no gcc works (msvc - works)
    };

    static Downloader *Create(const Hints &hints = Hints());
};

Downloader* Downloader::Create(const Hints &hints)
{
    std::cout << hints.numOfMaxEasyHandles << std::endl;
    return nullptr;
}

int main()
{
    return 0;
}

Вы можете сами поиграть с этим кодом на https://wandbox.org/ и увидеть ошибку:

prog.cc:16:58: error: default member initializer for 'Downloader::Hints::numOfMaxEasyHandles' required before the end of its enclosing class
     static Downloader *Create(const Hints &hints = Hints());
                                                          ^
prog.cc:11:37: note: defined here
         int32_t numOfMaxEasyHandles = 8;
                                     ^~~~

Почему gcc и clang не компилируют этот код даже с комментарием Hints() = default?Мои команды компиляции:

  1. $ g++ prog.cc -std=gnu++2a
  2. $ clang++ prog.cc -std=gnu++2a

Но если я раскомментирую Hints(){}, все три компилятора будут работать.Может быть, это ошибка компилятора?Заранее спасибо.

1 Ответ

0 голосов
/ 22 ноября 2018

Это ошибка clang и gcc, у нас есть отчет об ошибке clang для этого: инициализатор члена по умолчанию для 'm', необходимый в определении включающего класса для аргумента по умолчанию функции , который имеет следующий пример:

#include <limits>
class A
{
   public:
      class B
      {
         public:
            explicit B() = default;
            ~B() = default;

         private:
            double m = std::numeric_limits<double>::max();
      };

   void f(double d, const B &b = B{}) {}
};

int main()
{
   A a{};
   a.f(0.);
}

, который производит следующую похожую диагностику:

t.cpp(15,34):  error: default member initializer for 'm' needed within definition of enclosing class 'A' outside of member functions
   void f(double d, const B &b = B{}) {}
                                 ^
t.cpp(12,20):  note: default member initializer declared here
            double m = std::numeric_limits<double>::max();
                   ^

Ричард Смит указывает, что это ошибка:

По поводу комментария № 0: если мы хотимчтобы исправить это раз и навсегда, мы должны использовать ту же технику, которую мы используем для отложенного синтаксического анализа шаблона: научить Sema перезванивать в анализатор для анализа отложенных областей по требованию.Тогда мы бы только отклонили случаи, когда существует фактический цикл зависимости.

Хотя не объясняет почему в деталях.

...