Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ class name injection

According to the standard [class]/2:

… The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.…

Moreover, [basic.scope.pdecl]/9:

The point of declaration for an injected-class-name (Clause 9) is immediately following the opening brace of the class definition.

Finally, [basic.lookup.classref]/3 and its example:

If the unqualified-id is ~ type-name, the type-name is looked up …

struct A { };
struct B {
    struct A { };
    void f(::A* a);
};
void B::f(::A* a) {
    a-> ~ A(); // OK: lookup in *a finds the injected-class-name
}

So far, we can gather:

  1. In the scope of a class A, there exists a name A.
  2. That name is declared at the opening of the definition brace of class A.
  3. That name names a type.

If the above is correct, then why does the following code fails to compile (in MSVC2015):

struct inj
{};

typedef struct inj::inj inj2;

The error message

Error C2039 '{ctor}': is not a member of 'inj'

seems to be at odds with the standard:

Note: For example, the constructor is not an acceptable lookup result in an elaborated-type-specifier so the constructor would not be used in place of the injected-class-name. —end note

like image 517
Hector Avatar asked Mar 16 '23 05:03

Hector


1 Answers

Since the following code compiles and runs correctly in other compilers, it is a bug in MSVC2015.

#include <boost/type_index.hpp>
#include <iostream>

struct inj
{
    int g;
};

typedef struct inj::inj inj2;

int main()
{

    inj2 ii;
    std::cout << boost::typeindex::type_id_with_cvr<decltype(ii)>().pretty_name() << '\n';
}

UPDATE: Reported as bug.

like image 75
Hector Avatar answered Mar 23 '23 17:03

Hector