Edwin Rodríguez
Edwin Rodríguez

Reputation: 1257

strange typename usage c++11

I have the following code

#include <iostream>
#include <string>
using namespace std;

template<class T> struct Tpl;
template<>        struct Tpl<int>    { void print() { cout << "int"    << endl; } };
template<>        struct Tpl<string> { void print() { cout << "string" << endl; } };

int main() {
  typename Tpl<int>::Tpl{}.print();
  typename Tpl<int>::Tpl<string>{}.print();
  typename Tpl<int>::Tpl<int>{}.print();
  typename Tpl<int>::Tpl::Tpl{}.print();
  typename Tpl<string>::Tpl<int>{}.print();
  typename Tpl<int>::Tpl::Tpl<int>{}.print();
  typename Tpl<string>::Tpl::Tpl<int>::Tpl{}.print();
  typename Tpl<int>::Tpl<string>::Tpl<int>::Tpl<string>::Tpl<int>::Tpl<string>{}.print();
}

that gives the following output

int
string
int
int
int
int
int
string

My question is how typename works in these cases, specially in the last one where you can switch between different template arguments. I would like to know if this behavior is standard or if it's some weirdness on the compiler.

This is the info of the compiler:

> g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)

Upvotes: 8

Views: 377

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477040

This is because of [temp.local]/1:

Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name.

Upvotes: 9

Related Questions