error: anachronistic old-style base class initializer

error: anachronistic old-style base class initializer

以下代码在我尝试过的所有 GCC 版本(C++98、C++11 和 C++14 模式)上都会产生后续编译错误:

struct T
{
    T(void* x) : (x) {}
};

// main.cpp: In constructor 'T::T(void*)':
// main.cpp:3:18: error: anachronistic old-style base class initializer [-fpermissive]
//      T(void* x) : (x) {}
//                   ^
// main.cpp:3:16: error: unnamed initializer for 'T', which has no base classes
//      T(void* x) : (x) {}

当然,这显然是错误的代码,因为我实际上并没有初始化任何东西。

但为什么它是一个 base-class 初始化器,为什么它是 "anachronistic" 而不是简单的错误?它曾经有效吗?什么时候?这是什么意思?


我在网上发现的 only related references 当成员名称被意外宏化时,人们遇到了错误,实际上导致了与上面相同的代码:

#define bar
// ^ some library could have done this

struct T
{
    T(int x)
        : bar(x)   // effectively just `: (x)`
    {}

    int bar;       // will cause its own error
};

那些人从来没有发现错误的含义,尽管他们后来至少发现了他们的程序被破坏的原因。

在第一个 C++ 编译器 CFront 1984-5 版本的文档中找到:

The constructor can be written like this:

  vec.vec(int lb, int hb) : (hb-lb+1)
  {
      if (hb-lb<0) hb = lb;
      low = lb;
      high = hb; 
  }

The construct : (hb-lb+1) is used to specify the argument list needed for the base class constructor vector().

有道理,如果你仔细想想。大概添加了基 class 的显式命名以支持多重继承。 (当时不支持成员初始化列表——成员是无条件默认构造的——所以在多重继承之前,构造函数只能在那里初始化一件事。)

感谢 http://www.softwarepreservation.org/projects/c_plus_plus/ 存档文档。

...哇,我刚才 意识到"CFront" 是文字游戏。

事实上,这不是有效的标准 C++,因此我们必须查看该语言的历史记录,以找到它变得无效的时间点。

1989 年,在进一步定义“C++”(自 1985 年最初以该名称命名)以来,Stroustrup 宣布基础初始化已从该语言的先前版本发生变化,以应对多重继承:[1]

[p191] The C++ Programming Language [Stroustrup 1986] describes C++ as defined and implemented in August 1985. This paper describes the growth of the language since then and clarifies a few points in the definition. It is emphasized that these language modifications are extensions; C++ has been and will remain a stable language suitable for long term software development. The main new features of C++ are: multiple inheritance, type-safe linkage, better resolution of overloaded functions, recursive definition of assignment and initialization, better facilities for user-defined memory management, abstract classes, static member functions, const member functions, protected members, overloading of operator ->, and pointers to members. These features are provided in the 2.0 release of C++.

[p214] The syntax for initializing base classes and members has been extended to cope with multiple inheritance and the order of initialization has been more precisely defined. [..]

文本继续演示我们目前熟悉的 base-class 初始化语法,正如 Sneftel 已经指出的那样(省去了我翻阅更多旧文档的麻烦!),直到 1985 年才出现这种情况,在最初的 C++ 实现中,它本身是从“C with 类”演变而来的。因此,我们可以得出结论,C++ 2.0 在 1989 年引入了更熟悉的语法,而这个“不合时宜”的版本在此之前一直有效。

当然请注意,在问题的代码中,没有基础。因此,即使在 C++ 1.0 中,程序最终也不会成功编译。但是,我们发现了为什么语法会被这样解析。

值得注意的是,GCC 正在诊断晦涩难懂、被遗忘已久的语法,这些语法在近三十年的任何 C++ 化身中都无效。


[1] “C++ 的演变:1985 到 1989”,Bjarne Stroustrup,AT&T 贝尔实验室 1989; pdf

这在 ARM 的第 18.3.2 节中被具体描述为不合时宜。

这些功能的原因通常是为旧版本的 C++ 或使用 类 的 C 提供连续性。所有 "anachronisms" 都有不良特征。编译器不需要提供此类功能,但如果提供,则有义务允许程序员停用它 and/or 使用它时请注意。