Как называется эта необычная функция шаблона С++, используемая Boost.Spirit?
Ниже приведен код из документации Boost.Spirit x3. Он использует интересный синтаксис С++, который я никогда раньше не видел, что почти невозможно описать в поисковом запросе, не зная правильной терминологии. Является ли это сокращением для прямого объявления класса? Где эта функция упоминается в стандарте С++?
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);
}
Ответы
Ответ 1
Аргументы шаблона необязательно должны быть определены для использования. Использование "class roman" фактически объявляет класс roman.
Вот пример кода:
#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;
}
Как отмечают люди в комментариях выше, это отличает этот экземпляр шаблона. И для прямого ответа на вопрос, который у вас был, указание характера аргумента шаблона в создании экземпляра шаблона называется "специфицированным спецификатором типа".
Ответ 2
Это то же самое, что:
class roman;
x3::rule<roman, unsigned> const roman = "roman";
Другими словами, записывая class T
, где ожидается имя типа, сначала объявляет, что T
- это имя класса, а затем переходит к T
в качестве имени типа, используемого для остальной части выражения.
Обратите внимание, что в С++ не существует столкновения между typename roman
и именем переменной roman
, объявленным здесь; это разрешено.
Другой случай этого может произойти без шаблонов, например:
void func( class bar *ptr );
является правильным, если bar
не объявлен; он объявляет bar
, а затем объявляет функцию для указания указателя на bar
.