10

I scoured the C++11 standard (well, the n3242 draft) and the internet but could not find a precise answer. The code below compiles fine with clang 3.2 and g++ 4.7.2 as well as Visual Studio 2010, but I would expect to get an error instead.

#include <iostream>
#include <typeinfo>


typedef int a_t;


namespace a_ns
{
class a_t {};
}


using a_ns::a_t;


int main()
{
    a_t a;
    std::cout << typeid(a).name() << std::endl;
    return 0;
}

Built with:

clang -std=c++11 -pedantic -Wall -o a a.cpp -lstdc++
g++ -std=c++11 -pedantic -Wall -o a a.cpp -lstdc++
cl -EHsc -GR a.cpp

clang and g++ generated executables print "i", which seems to indicate that the a is of type int and the typedef prevailed. cl generated executable prints "class a_ns::a_t" which seems to indicate that Visual Studio liked the using declaration more.

I would expect the code not to compile according to the following standard excerpts. I would expect an error similar to "target of using declaration conflicts with declaration already in scope".

7.1.3.6 Similarly, in a given scope, a class or enumeration shall not be declared with the same name as a typedef-name that is declared in that scope and refers to a type other than the class or enumeration itself.

7.3.3.1 A using-declaration introduces a name into the declarative region in which the using-declaration appears.

7.3.3.2 Every using-declaration is a declaration [...]

There's probably something I am missing in the standard that explains this behavior (or I am just too tired to see the obvious), but I cannot seem to find it.

Thank you.

stephaneyfx
  • 306
  • 1
  • 8

1 Answers1

4

That's right and what you have shown makes the code invalid. There is also 3.3.1p4 which makes it invalid too (see 7.3.3p13).

For a reality test, I tested with ICC and it rejects it as expected.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • If the body of `main()` were empty, would that program be invalid as well? Paragraph 7.1.3/6 says "*In a given scope, a typedef specifier shall not be used to **redefine** the name of any type declared in that scope to refer to a different type.* [ Example: `class complex { / ... / }; typedef int complex; // error: redefinition` —end example *] "*. In the question, the `typedef` does not "redefine" the name. When moved after the `using` declaration, all compilers emit an error. – Andy Prowl Feb 27 '13 at 23:13
  • @andy if main was empty, it would be invalid aswell, according to the quotes we found. whether some other quote also applies is irrelevant then. normally, a redefinition of a name occurs for `class A {}; typedef A A;` (first it is only a class-name. then it is also a typedef-name. the name is redefined, because afterwards there is still only a single name, but it has both syntactical attributes. this is different from the C model). – Johannes Schaub - litb Feb 27 '13 at 23:16