web-dev-qa-db-fra.com

Modèle dans le modèle: pourquoi "` >> 'devrait être `>>' dans une liste d'arguments de modèle imbriqués"

Je sais que lorsque nous utilisons un modèle dans un autre modèle, nous devons l'écrire comme ceci:

vector<pair<int,int> > s;

et si nous l'écrivons sans les espaces:

vector<pair<int,int>> s;

nous obtiendrons une erreur:

`>> 'doit être`>>' dans une liste d'arguments de modèle imbriqués

Je vois que c'est compréhensible, mais je ne peux pas m'empêcher de me demander, dans quels cas cela sera-t-il vraiment ambigu?

49
zw324

Parfois, vous voulez que ce soit >>. Considérer

boost::array<int, 1024>>2> x;

En C++ 03, cela analyse et crée un tableau de taille 256.

48

Ce ne sera jamais ambigu. Ceci est prouvé par le fait qu'en C++ 0x vous n'avez pas besoin d'écrire d'espace entre la fermeture du template >s plus.

Le fait est que les compilateurs préfèrent tokeniser l'entrée aussi indépendamment du contexte que possible. Étant donné que C++ n'est pas un langage indépendant du contexte de toute façon, l'ajout d'un seul cas particulier ne rendra pas les choses particulièrement difficiles.

28
Armen Tsirunyan

Dans la norme actuelle, la tokenisation est gourmande, donc >> sera traité comme un seul jeton, de la même manière que a +++ b sera analysé comme a ++ + b. Cela a changé et la nouvelle norme. Bien que cela nécessite plus de travail de la part des implémenteurs du compilateur, il a été estimé que dans l'ensemble, cela en valait la peine (et certains grands compilateurs implémentent déjà cela en tant qu'extension).

C++ est vraiment incroyablement difficile à analyser - beaucoup plus difficile que la plupart des autres langages. C'est un langage très cohérent, mais tant de travail est fait entre la création de jetons d'entrée et la compréhension de l'analyse grammaticale de la syntaxe, que les choses qui semblent être simples pour un compilateur ne le sont souvent pas.

L'historique ">> "L'opérateur est un opérateur. Il est" identifié "car le fichier source est divisé en jetons. Ces jetons sont ensuite" compris "dans un certain contexte lors de l'analyse grammaticale (longtemps après la fin de la tokenisation).

Si vous avez fait une analyse grammaticale pendant que vous avez symbolisé, alors vous avez des "aides" pour aider à la distinction que ">> "doit être considéré comme deux fermetures à une déclaration (ou définition) de modèle. Pourtant, ce n'est historiquement pas la façon dont les compilateurs C++ historiques fonctionnent. aider à résoudre ces ambiguïtés.)

Oui, la nouvelle norme C++ 0x change cela et oblige les fournisseurs de compilateurs à réécrire leurs implémentations pour lever l'ambiguïté ">> "dans votre cas. Donc, ce ne sera jamais ambigu à l'avenir. Cependant, les anciens compilateurs C++ ne peuvent pas gérer cela, donc il peut être considéré comme une" bonne pratique "de garder votre code compatible avec l'espace entre les '> 'caractères pour l'instant.

7
charley

Évitez cette erreur en définissant un dialecte C++ approprié. Par exemple, avec gcc 4.9, le fichier suivant ne se compile pas avec g++:

#include <vector>
#include <utility>

int main()
{
    using namespace std;
    vector<pair<int, int>> v; // compile error!
    return 0;
}

Allons au fond des choses:

#include <iostream>

int main()
{
    std::cout << __cplusplus << std::endl;
    return 0;
}

Compilé avec juste g++ test.cpp ce code imprime 199711. Bien que gcc 4.9 soit sorti en 2014, le dialecte C++ par défaut est C++ 98 avec GNU. C++ 98 nous oblige à écrire vector<pair<int, int> >. Si tu veux vector<pair<int, int>> plus de compilation avec -std=c++11 ou -std=gnu++11.

1
Andreas Spindler

Cela dépend du compilateur. Visual Studio n'impose pas cela, c'est-à-dire que les deux fonctionnent tandis que g ++ produit une erreur. Je pense que cela dépend de l'implémentation du compilateur.

1
iBrAaAa

Syntaxe du flux

cin >> var;

Contre

Syntaxe de modèle imbriqué

For<Bar<Barz>>

Première phase du compilateur, l'analyseur lexical ne pourra pas reconnaître.

0
Mani