Question Pourquoi le compilateur essaie-t-il d'instancier un modèle que je ne instancie nulle part ailleurs?


Mis à jour ci-dessous.
Voici le code complet que j'ai dans ma main.cpp:

template<class T>
struct other_traits;

template<class T>
struct some_traits{
    typedef decltype(&T::operator()) Fty;
    typedef typename other_traits<Fty>::type type;
};

int main(){
}

Mais je reçois les erreurs suivantes avec Visual Studio 2010 tout en g ++ compile bien:

src \ main.cpp (9): erreur C2146: erreur de syntaxe: manquante ';' avant identifiant 'type'
  --src \ main.cpp (10): voir la référence à l'instanciation du modèle de classe 'some_traits<T>'être compilé
  src \ main.cpp (9): erreur C2868: 'some_traits<T>::type': syntaxe illégale pour l'utilisation de la déclaration; nom qualifié attendu

(J'aime ce dernier, total wtf.)

Puis-je prendre cela comme un bug dans VC10 ou y a-t-il une bonne raison pour l'instanciation précoce? Ou est-ce un bug avec decltype qui fait que le compilateur pense que Fty n'est pas un nom dépendant?


Mettre à jour: J'ai essayé de tromper le compilateur en pensant que Fty est un nom dépendant utilisant une classe de base à hériter de:

template<class T>
struct other_traits;

template<class R, class C>
struct other_traits<R (C::*)()>{
    typedef R type;
};

template<class Fty>
struct base_traits{
    typedef typename other_traits<Fty>::type type;
};

template<class T>
struct some_traits
    : public base_traits<decltype(&T::operator())>
{};

Mais le compilateur essaie toujours d’instancier / compiler tout sur place, crachant ces erreurs:

src\main.cpp(13): error C2039: 'type' : is not a member of 'other_traits<T>'
          with
          [
              T=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'base_traits<Fty>' being compiled
          with
          [
              Fty=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'some_traits<T>' being compiled
src\main.cpp(13): error C2146: syntax error : missing ';' before identifier 'type'
src\main.cpp(13): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
src\main.cpp(13): error C2602: 'base_traits<Fty>::type' is not a member of a base class of 'base_traits<Fty>'
          with
          [
              Fty=
          ]
          src\main.cpp(13) : see declaration of 'base_traits<Fty>::type'
          with
          [
              Fty=
          ]
src\main.cpp(13): error C2868: 'base_traits<Fty>::type' : illegal syntax for using-declaration; expected qualified-name
          with
          [
              Fty=
          ]

Notez que les paramètres du modèle sont vide. Des idées?


15
2018-06-07 10:40


origine


Réponses:


Il semble être un Punaise (s'il n'y a pas de drapeau spécial défini comme indiqué ci-dessous). Voici un extrait de Site Oracle pour les modèles C ++:

7.2.2


2
2018-06-07 11:28



Je pense que vous êtes tombé sur un bug lié à une instanciation prématurée lorsque le compilateur voit decltype


1
2018-06-08 02:10



template<class T>
struct other_traits; // <-- I don't see a "type" attribute in this struct

template<class T>
struct some_traits{
    typedef decltype(&T::operator()) Fty;
    typedef typename other_traits<Fty>::type type; // <-- Here you are trying to access other_traits<T>::type which doesn't exist
};

int main(){
}

0
2018-06-07 13:19



Vous faites une hypothèse ici, qui est techniquement incorrecte. abordons cela en premier.

Vous supposez qu'une erreur de syntaxe signifie qu'un modèle est instancié. C'est pas comme ça devrait être compilé. Un modèle est d'abord compilé avant l'instanciation. C'est la phase dans laquelle les noms non dépendants sont recherchés. Des erreurs de syntaxe peuvent certainement être trouvées dans cette phase. Par exemple, tout ce qui est nécessairement une déclaration indépendamment des arguments du modèle doit se terminer par un ;.

Maintenant, la bonne question est de savoir si le compilateur est correct en considérant les spécialisations de other_traits<T>. Il n'y a bien sûr aucune spécialisation de ce type à la ligne 9, même s'il pourrait y avoir des spécialisations plus tard. Mais serait le point d'instanciation pertinent pour ceux? Je devrais regarder ça (désolé, AFS loin de Standardother_traits <T> serait la ligne 9, puis là sont aucune spécialisation, et other_traits<Fty>::type est invalide. Si le point d'instanciation pour other_traits<Fty>::type serait le même que le point d'instanciation pour some_traits<T>, c'est-à-dire aucun, alors other_traits<Fty>::type devrait être accepté en phase 1.


0
2018-06-07 20:27