Как называется эта необычная функция шаблона C++, используемая Boost.Дух?


приведенный ниже код от импульс.Документация Spirit x3. Он использует интересный синтаксис C++, который я никогда раньше не видела, который почти невозможно описать в поисковом запросе, не зная правильной терминологии. Является ли это сокращением для прямого объявления класса? Где эта функция упоминается в стандарте 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);
}
2   51   2016-08-31 03:12:27

2 ответа:

аргументов шаблона не обязательно должны быть использованы. Использование "класса 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;
}

как люди указали в комментариях выше, это отличает этот экземпляр шаблона. И чтобы напрямую ответить на вопрос, который у вас был, указание природы аргумента шаблона в экземпляре шаблона называется "разработанным спецификатором типа".

это то же, что:

class roman;

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

другими словами, пишет class T где ожидается имя типа, сначала объявляет, что T - это имя класса, а затем с T в качестве имени типа используется для остальной части выражения.

обратите внимание, что в C++ нет никакого столкновения между typename roman и имя переменной roman объявляется здесь; это разрешено.


другой случай этого может произойти без шаблонов, например:

void func( class bar *ptr );

является правильным, если bar необъявленный; он объявляет bar а затем объявляет функцию, чтобы взять указатель на bar.