What I read in the C++ standard about injected class names contradicts (as I see it) with the behavior of a sample program I will present shortly. Here's what I read:
From 3.4 (paragraph 3)
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.
From 9 (paragraph 2)
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.
From these I understand that the following is a well-formed translation unit and it compiles successfully.
#include <vector>
class X: std::vector<int>
{
vector mem;
};
However, I would suppose that the following should have produced an error, but it doesn't
#include <vector>
class X: std::vector<int>, std::vector<char>
{
vector mem; //compiles OK... mem is apparently std::vector<int>
};
Since the name vector
is injected into both std::vector<int>
and std::vector<char>
as as if a public member name, then it should be inherited by X and therefore the name vector
in X
should be ambiguous. Am I missing something?
P.S. I am using MSVC9.0
Ambiguity errors occur when erasure causes two seemingly distinct generic declarations to resolve to the same erased type, causing a conflict.
When you derive classes, ambiguities can result if base and derived classes have members with the same names. Access to a base class member is ambiguous if you use a name or qualified name that does not refer to a unique function or object.
Class: A class in C++ is the building block that leads to Object-Oriented programming. It is a user-defined data type, which holds its own data members and member functions, which can be accessed and used by creating an instance of that class. A C++ class is like a blueprint for an object.
I found it! It's right there in the standard! I was right! It should be ambiguous!
Clause 14.6.1 Paragraph
A lookup that finds an injected-class-name (10.2) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is followed by a template-argument-list, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous. [Example:
template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char>
{
typename Derived::Base b; // error: ambiguous typename
Derived::Base<double> d; // OK
};
—end example]
Bottom line: This is yet another Microsoft compiler BUG. Disabling language extensions doesn't help either.
No, you are not missing anything, and your compiler seems to behave buggy. You can see how gcc handles it here: http://ideone.com/MI9gz
Its error message is:
prog.cpp:4:4: error: reference to 'vector' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_vector.h:171:5: error: candidates are: class std::vector<char> std::vector<char>::vector
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_vector.h:171:5: error: class std::vector<int> std::vector<int>::vector
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