2015-12-13 4 views
8

Ich habe den folgenden Codeseltsame Type-Name Verwendung C++ 11

#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(); 
} 

, die die folgende Ausgabe

int 
string 
int 
int 
int 
int 
int 
string 

Meine Frage ist, wie typename Arbeiten in diesen Fällen besonders in der letzten gibt wo Sie können zwischen verschiedenen Vorlagenargumenten wechseln. Ich würde gerne wissen, ob dieses Verhalten Standard ist oder ob es etwas Verrücktes auf dem Compiler ist.

Dies ist die Info des Compilers:

> 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) 

Antwort

9

Dies liegt daran, von [temp.local]/1:

Wie normalen (nicht-Template) Klassen, haben Klassen-Templates eine injected-class-name (Abschnitt 9). Der eingegebene Klassenname kann als Vorlagenname oder Typname verwendet werden.

+1

Wow, sehr interessant! So ist es wie jede Klasse ist wie 'Klasse SomeName {mit SomeName = SomeName; }; '? –

+2

Art von. Siehe http://stackoverflow.com/questions/25549652/c-why-is-there-injected-class-name –

+0

@ melak47: Ich bin nicht genau sicher, ob der 'typeName' erforderlich ist. Ich habe nur versucht zu erklären, warum der Name als Typname und als Vorlagenname verwendet werden kann ... –