error: anachronistic old-style base class initializer

匿名 (未验证) 提交于 2019-12-03 02:47:02

问题:

The following code produces the subsequent compilation error on all versions of GCC that I've tried, in C++98, C++11 and C++14 modes:

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) {} 

Sure, it's clearly broken code because I'm not actually initialising anything.

But why is it a base-class initialiser and why is it "anachronistic", rather than simply wrong? Was it once valid? When? And what did it mean?


The only related references I've found to this on the web have been people coming across the error when a member name was accidentally macro'd out, effectively resulting in the same code as above:

#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 }; 

Those people never did find out what the error meant, although they later at least discovered why their program was broken.

回答1:

Found in the documentation for the 1984-5 release of CFront, the first C++ compiler:

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().

Makes sense, if you think about it. Presumably the explicit naming of the base class was added to support multiple inheritance.

Credit to http://www.softwarepreservation.org/projects/c_plus_plus/ for archiving the documents.

...and wow, I just now realized that "CFront" was a play on words.



回答2:

Indeed this is not valid standard C++, so we must look to the annals of the language's history to find the point at which this became invalid.

In 1989, when further defining "C++" since its original inception under that name in 1985, Stroustrup declared that base initialisation had changed from the language's previous incarnations, in order to cope with multiple inheritance: [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. [..]

The text goes on to demonstrate the base-class initialisation syntax with which we are presently familiar and, as Sneftel has already pointed out (saving me the trouble of hunting through any more old documents!), this had not been the case as late as 1985, in the original C++ implementation that itself evolved out of "C with Classes". So, we can conclude that C++ 2.0 introduced the more familiar syntax in 1989 and this "anachronistic" version was valid until then.

Note, of course, that in the question's code, there is no base. So, even in C++ 1.0, the program would ultimately not have successfully compiled. However, we have discovered why the syntax is being parsed in such a way.

It's remarkable that GCC is diagnosing obscure, long-forgotten syntax that has not been valid in any incarnation of C++ for almost thirty years.


[1] "The Evolution of C++: 1985 to 1989", Bjarne Stroustrup, AT&T Bell Laboratories 1989; pdf



回答3:

This was described specifically in the ARM, Section 18.3.2 as an anachronism.

The reason for such features was, typically, providing continuity to older versions of C++ or to C with classes. All "anachronisms" had undesirable characteristics. Compilers were not required to provide such features but, if they did, were obliged to permit a programmer to deactivate it and/or be warned about using it.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!