2015-08-19 1 views
4

Dans cette ligne:Quel est le type exact de "" lorsque déduit par `auto`?

auto a = "Hello World"; 

Quelle est la exacte Type de a? Je devinerais char[] ou const char* const mais je ne suis pas sûr.

+2

De cette façon, il se désintègre à 'const char *' –

+0

On dirait 'const char * ', sur ma version de g ++ (4.8.1), à la fois' typeid (a) .name() 'et' typeid (const char *). name() 'retourne la même valeur alors que' typeid (const char [ ]). name() 'ou' typeid (b) .name() '(' const char b [] = "Bonjour tout le monde"; ') retourne quelque chose d'autre. – Holt

Répondre

10

N4296 2.13.5/8

chaînes littérales ordinaires et les littéraux de chaîne UTF-8 sont également appelés à chaînes littérales aussi étroites. Une chaîne littérale étroite a le type "tableau de n const char", où n est la taille de la chaîne définie ci-dessous, et a une durée de stockage statique (3.7).

Mais comme la variable est initialisée comme dans votre code, elle est en réalité const char*, vous pouvez le vérifier comme ceci.

template<typename> struct TD; 

int main() 
{ 
    auto a = "Hello World"; 
    TD<decltype(a)> _; 
} 

seront ici Erreur de compilation dans laquelle vous pouvez voir le type de TD instance réelle, quelque chose comme ça avec clang

error: implicit instantiation of undefined template 'TD<const char *>' 

N4296 7.1.6.4

Si l'espace réservé est le spécificateur de type automatique, le type déduit est déterminé en utilisant les règles pour la déduction d'argument de modèle.

template<typename> struct TD; 

template<typename T> 
void f(T) 
{ 
    TD<T> _; 
} 

int main() 
{ 
    auto c = "Hello"; 
    TD<decltype(c)> _; 
    f("Hello"); 
} 

Les deux objets instanciés de type TD a pour type TD<const char*>.

N4926 14.8.2.1

déduction argument du modèle se fait en comparant chaque fonction type de paramètre de modèle (appelons-P) avec le type de l'argument correspondant de l'appel (appeler A) tel que décrit au dessous de.

Si P est pas un type de référence:

Si A est un type de réseau, le type de pointeur produite par la conversion standard à matrice pointeur (4,2) est utilisé à la place de A pour déduction de type

+0

* "vous pouvez le vérifier comme ceci" TD _; '" * - comment cela vérifie-t-il? Non seulement TD est incomplet de telle sorte qu'il ne peut pas être défini, mais si cela est corrigé, cela fonctionnerait pour n'importe quel type - voir [ici] (http://coliru.stacked-crooked.com/a/4469e06eef32b3b9). –

+1

@TonyD le fait est qu'un type incomplet déclenche une erreur de compilation qui affiche le type utilisé pour instancier ce type incomplet. Une solution plus pratique est 'template void TD() {std :: cout << __ PRETTY_FUNCTION __ << std :: endl; } ' –

+0

@TonyD c'est vérifier. Ne pas définir TD. Vous allez voir le type de TD à la compilation comme erreur de compilation. – ForEveR

2

Sauf si vous avez des raisons de penser que ce serait la mise en œuvre ou non défini, pouvez tester:

#include <iostream> 

template <typename T> void f() { std::cout << "other\n"; } 
template <> void f<const char*>() { std::cout << "const char*\n"; } 
template <> void f<const char* const>() 
    { std::cout << "const char* const\n"; } 
template <> void f<const char(&)[12]>() { std::cout << "const char[12]\n"; } 

int main() 
{ 
    auto a = "Hello World"; 
    f<decltype(a)>(); 
} 

sortie:

const char* 

Vérifier que ++a est un autre indice compile (il fait), et alors que la mise en œuvre définie #include <typeinfo>/typeid(a).name() peut souvent aider à répondre à ces questions.

Passez à auto& a et vous verrez a changements à const char(&)[12].

1

Vous pouvez imprimer le type de l'aide typeinfo

int main() 
{ 
    auto a = "Hello World"; 
    std::cout << "type is: " << typeid(a).name() << '\n'; 
} 

sur gcc il imprimera

pi est: PKc

qui signifie pointeur vers un char constant Si vous êtes dans Windows la sortie sera beaucoup plus lisible, mais vous vous habituerez à cette syntaxe aussi.

Si vous en savez plus ou moins que vous tapez une nouvelle recherche, vous pouvez également vérifier si deux types sont équivalents:

#include <typeinfo> 
std::cout << std::is_same<const char*, decltype(a)>::value << std::endl; 
+0

Utilisez C++ filt pour démêler les noms. Quoi qu'il en soit, typeid n'est pas le meilleur pour montrer les types car il élimine les qualificatifs cv. – edmz

+0

Vous avez raison, je ne le savais pas, j'ai été troublé par le fait que 'char * b = const_cast (a); std :: cout << "le type est:" << typeid (b) .name() << '\ n'; 'sorties' Pc' –

+0

Je ne recommanderais pas typeid.name qui peut retourner les mauvais types comme Scott Meier explique à http://www.aristeia.com/TalkNotes/C++TypeDeductionandWhyYouCareCppCon2014.pdf (Diapositive 32) – Guillermo