Le code ci-dessous provient de la documentation Boost.Spirit x . Il utilise une syntaxe C++ intéressante que je n'ai jamais vue auparavant, qui est presque impossible à décrire dans une requête de recherche sans connaître la terminologie appropriée. Est-ce 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);
}
Les arguments d'un modèle ne doivent pas nécessairement être définis pour être utilisés. L'utilisation de "classe romaine" déclare en fait la classe romaine.
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 vous posiez, la spécification de la nature de l'argument de modèle dans une instanciation de modèle est appelée "spécificateur de type élaboré".
C'est la même chose que:
class roman;
x3::rule<roman, unsigned> const roman = "roman";
En d'autres termes, écrire class T
où un nom de type est attendu, déclare d'abord que T
est le nom d'une classe, puis continue avec T
comme nom de type utilisé pour le reste de l'expression.
Notez qu'en C++ il n'y a pas de conflit entre le nom de type roman
et le nom de variable roman
déclaré ici; c'est permis.
Un autre cas de cela peut se produire sans modèles, par exemple:
void func( class bar *ptr );
est correct si bar
n'est pas déclaré; il déclare bar
puis déclare la fonction pour prendre un pointeur sur bar
.