c++ - 尝试理解编译器错误信息 : default member initializer required before the end of its enclosing class

标签 c++ c++11 c++14 c++17

我用三个编译器(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;
                                     ^~~~

为什么即使取消注释 Hints() = default,gcc 和 clang 也无法编译这段代码? 我的编译命令:

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

但是如果我取消注释 Hints(){} 所有三个编译器都可以工作。也许是编译器错误?提前致谢。

最佳答案

这是一个 clang 和 gcc 错误,我们有一个 clang bug report for this: default member initializer for 'm' needed within definition of enclosing class for default argument of function其中有以下示例:

#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();
                   ^

Richard Smith 指出这是一个错误:

Regarding comment#0: if we want to fix this once-and-for-all, we should use the same technique we use for delayed template parsing: teach Sema to call back into the parser to parse the delayed regions on-demand. Then we would only reject the cases where there's an actual dependency cycle.

虽然没有详细解释原因。

关于c++ - 尝试理解编译器错误信息 : default member initializer required before the end of its enclosing class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53408962/

相关文章:

c++ - Scoped Enums(枚举类)关系运算符

c++ - CMake 包含第 3 方项目

c++ - is_constexpr 在 C++11 中可能吗?

c++ - 列出具有私有(private)成员的类的初始化

c++ - 将 time_point 转换为字符串的最漂亮方法是什么?

c++ - 如何从 C++ 中的整数除法返回 double ?

c++ - 如何确定我们使用的是真正的 48、56 还是 64 位指针

c++ - std::move(*this) 是一个好的模式吗?

c++ - 如何使用基元和特征创建尾随返回类型?

c++ - 如何在编译时从复杂代码中暗示数组长度(const int)