2009-08-25 7 views
1

J'ai essayé cet exemple de "C++ Template - Le guide complet" par Nicolai M. JosuttisComportement étrange des arguments de modèle dans Visual C++?

#include <iostream> 

using namespace std; 

template< typename T > 
class List { 
}; 

typedef enum { RED, GREEN, BLUE } *color_ptr; 

int main() { 
    struct Local { 
     int x; 
    }; 

    List<Local> l; // error : local type in template argument 
    List<color_ptr> l1; // error : unamed type in template argument. 

    return 0; 
} 

Avec g ++ sous Ubuntu 9.04, je suis arrivé erreurs du compilateur. Cependant, ce morceau de code a été compilé avec succès dans Visual C++ 2008. Et comme je l'ai lu dans le livre: "Les arguments de type de modèle sont les" valeurs "spécifiées pour les paramètres de type de gabarit. 1. Les classes et énumérations locales (en d'autres termes, les types déclarés dans une définition de fonction) ne peuvent pas être impliquées dans les arguments de type template 2. Les types impliquant des types de classe sans nom ou des types d'énumération sans nom ne peuvent pas être des arguments de type template (les classes sans nom ou énumérations qui sont donnés un nom par une déclaration typedef sont OK.) donc, il y a une erreur dans Visual C++?

+0

Est-ce le mode de débogage ou de libération? – jkeys

+0

En cas de doute, essayez http://www.comeaucomputing.com/tryitout/. FWIW, il est d'accord avec g ++, donc ce serait un problème avec VC. – sbi

+0

Le livre en question a été co-écrit par un développeur de comeau (EDG). –

Répondre

0

Vérifiez si vous compilez avec des extensions Microsoft (/ Ze).

1

Ce sont des extensions autorisées à la norme sur la partie MSVC. MS fait un travail décent documentant options de son compilateur, la conformité ou la déviance des normes, & c; en particulier, comme documenté here, /Za dira le compilateur de marquer comme des écarts d'erreurs de la norme (qu'il appelle particulièrement "ansi C++" au lieu de ISO ;-).

+1

Clairement MS sont des patriotes. Peut-être que je devrais l'appeler BSI C++, surtout quand je fais référence à ma copie reliée :-) –

3

Il existe de nombreux autres cas où vous trouvez que le livre diverge du comportement de VC++. Les exemples sont les outils d'ambiguïté typename et template et la liaison de références non-const aux valeurs rvalues.

Dans ce cas, bien sûr, le comportement de G ++ est correct, comme le dit le livre. Essayez les modifications suivantes

typedef enum color_type { RED, GREEN, BLUE } *color_ptr; 

template< typename T > 
class List { 
}; 

// not really local anymore :) 
struct Local { int x; }; 
int main() { 
    List<Local> l; 
    List<color_type> l1; 
} 

Le prochain standard C++ (C++ 0x) autorise les types locaux en tant qu'arguments de modèle.


Veuillez noter ce que le livre signifie en donnant un nom à un type avec typedef. Cela ne s'applique pas à ce qui suit, car le nom A ne nomme pas le type d'énumération, mais un type de pointeur.

typedef enum { X } *A; 

Ainsi, lorsque vous utilisez A ou dans votre exemple color_ptr, alors vous n'allez pas sûr. Techniquement, ce nom est un type de pointeur vers un type sans lien, ce qui n'est pas autorisé en tant qu'argument de modèle.


Notez que vous pouvez mettre Local dans un espace de noms sans nom pour faire le type locale à l'unité de traduction en cours, mais encore le type acceptable comme argument de modèle de type. De cette façon, si vous voulez juste avoir un type "scratch" pour quelque chose comme un objet fonction, la structure ne sera pas en conflit avec une structure définie dans un fichier différent.

namespace { 
    // not really local anymore, but "translation unit local" :) 
    struct Local { int x; }; 
}