51 votes

Quel est le nom de cette particularité de modèle C++ utilisé par Boost.Spirit ?

Le code ci-dessous provient de la documentation Boost.Spirit x3 . Il utilise une syntaxe C ++ intéressante que je n'ai jamais vue auparavant, qu'il est presque impossible de décrire dans une requête de recherche sans connaître la terminologie appropriée. S'agit-il d'un raccourci pour la déclaration anticipée d'une classe? Où cette fonctionnalité est-elle mentionnée dans la norme C ++?

 namespace parser
{
    using x3::eps;
    using x3::lit;
    using x3::_val;
    using x3::_attr;
    using ascii::char_;

    auto set_zero = [&](auto& ctx){ _val(ctx) = 0; };
    auto add1000 = [&](auto& ctx){ _val(ctx) += 1000; };
    auto add = [&](auto& ctx){ _val(ctx) += _attr(ctx); };

    // What is this? This is the very first use of the identifier `roman`.
    x3::rule<class roman, unsigned> const roman = "roman";
    //       ^^^^^^^^^^^

    auto const roman_def =
        eps                 [set_zero]
        >>
        (
            -(+lit('M')     [add1000])
            >>  -hundreds   [add]
            >>  -tens       [add]
            >>  -ones       [add]
        )
    ;

    BOOST_SPIRIT_DEFINE(roman);
}
 

41voto

Robert Prévost Points 1369

Les arguments d'un modèle ne doivent pas nécessairement être définis pour être utilisés. L'utilisation de "class roman" déclare en fait la classe roman.

Voici un exemple de code:

 #include <iostream>
template <class T> void foo();
template<> void foo<class roman>()
{
    // allowed because roman is declared
    roman* pointer1;
    // not allowed because romania is not declared
    // romania* pointer2;
    std::cout << "Hello world!" << std::endl;
    return;
}
int main(int argc, char** argv) {
    return 0;
}
 

Comme les gens l'ont souligné dans les commentaires ci-dessus, cela distingue cette instanciation du modèle. Et pour répondre directement à la question que vous avez posée, la spécification de la nature de l'argument de modèle dans une instanciation de modèle s'appelle un «spécificateur de type élaboré».

27voto

Matt McNabb Points 14273

C'est la même chose que:

class roman;

x3::rule<roman, unsigned> const roman = "roman";

En d'autres mots, l'écriture class T où un typename est attendu, déclare d'abord qu' T est le nom d'une classe, et ensuite procède à l' T comme le nom du type utilisé pour le reste de l'expression.

Notez qu'en C++, il n'y a pas de choc entre le typename roman , et le nom de la variable roman être déclarés ici; ce qui est autorisé.


Un autre cas de ce qui peut arriver sans modèles, par exemple:

void func( class bar *ptr );

est correct si bar est non déclarées; il déclare bar et déclare alors la fonction de prendre un pointeur vers bar.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X