I had the following code, which was basically,
class foo { public: void method(); }; void foo::foo::method() { }
I had accidentally added an extra foo:: in front of the definition of foo::method. This code compiled without warning using g++(ver 4.2.3), but errored out using Visual Studio 2005. I didn't have a namespace named foo.
Which compiler is correct?
In the strict mathematical sense, C isn't a subset of C++. There are programs that are valid C but not valid C++ and even a few ways of writing code that has a different meaning in C and C++. However, C++ supports every programming technique supported by C95 (C90 plus an Amendment) and earlier.
You can add C and C++ code to your Android project by placing the code into a cpp directory in your project module. When you build your project, this code is compiled into a native library that Gradle can package with your app.
You can make use of code and reuse it to the hilt. C++ is a superset of C.
Constructs valid in C but not in C++ C++ enforces stricter typing rules (no implicit violations of the static type system), and initialization requirements (compile-time enforcement that in-scope variables do not have initialization subverted) than C, and so some valid C code is invalid in C++.
If I read the standard correctly, g++ is right and VS is wrong.
ISO-IEC 14882-2003(E), §9.2 Classes (pag.153): A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.
Following on the comments below, it's also particularly useful to retain the following concerning the actual Name Lookup rules:
ISO-IEC 14882-2003(E), §3.4-3 Name Lookup (pag.29): The injected-class-name of a class (clause 9) is also considered to be a member of that class for the purposes of name hiding and lookup.
It would be odd if it wasn't, given the final part of text at 9.2. But as litb commented this reassures us that indeed g++ is making a correct interpretation of the standard. No questions are left.
Krugar has the correct answer here. The name that is is being found each time is the injected class name.
The following is an example which shows at least one reason why the compiler adds the injected class name:
namespace NS { class B { // injected name B // #1 public: void foo (); }; int i; // #2 } class B // #3 { public: void foo (); }; int i; // #4 class A :: NS::B { public: void bar () { ++i; // Lookup for 'i' searches scope of // 'A', then in base 'NS::B' and // finally in '::'. Finds #4 B & b = *this; // Lookup for 'B' searches scope of 'A' // then in base 'NS::B' and finds #1 // the injected name 'B'. } };
Without the injected name the current lookup rules would eventually reach the enclosing scope of 'A' and would find '::B' and not 'NS::B'. We would therefore need to use "NS::B" everywhere in A when we wanted to refer to the base class.
Another place that injected names get used are with templates, where inside the class template, the injected name provides a mapping between the template name and the type:
template <typename T> class A { // First injected name 'A<T>' // Additional injected name 'A' maps to 'A<T>' public: void foo () { // '::A' here is the template name // 'A' is the type 'A<T>' // 'A<T>' is also the type 'A<T>' } };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With