Ambiguous injected class name is not an error
Asked Answered
D

2

19

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

Dominance answered 11/8, 2011 at 11:28 Comment(6)
Is the second clause not referring to X in your example? I.e. is the injected-class-name not X rather than vector? I think that is the case, and if so the quotes are irrelevant to the code, but still the behavior of that compiler does not seem to be correct either there is no reason to prefer std::vector<int> over std::vector<char> and that means that there should be an ambiguity error being triggered.Candi
@David: In class X yes, but vector is injected as a public name in both the bases... So it should be visible(and ambiguous) inside X as well - as in the first exampleDominance
@Armen Tsirunyan: For std::vector, A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.: std namespace; The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.: std::vector template. I still think that those quotes are not related to the particular code example.Candi
@David: because the injected-class-name is injected with public visibility, it is available to derived classes, which is what occurs here.Millicentmillie
:) Thanks @Matthieu, I was not looking beyond the first line of code :)Candi
@ArmenTsirunyan: always refer to more than compilers ! And specially don't work with buggy VC compiler alone!Sayette
D
17

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.

Dominance answered 11/8, 2011 at 11:55 Comment(0)
T
4

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
Televisor answered 11/8, 2011 at 11:52 Comment(1)
Ah, yes, indeed! I just found the quote from the standard myself (see my answer)Dominance

© 2022 - 2024 — McMap. All rights reserved.