web-dev-qa-db-ja.com

Boost.Spiritで使用されるこの珍しいC ++テンプレート機能の名前は何ですか?

以下のコードは Boost.Spirit x3 documentation からのものです。これまで見たことのない興味深い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);
}
51
Barrett Adair

テンプレートへの引数は、使用するために必ずしも定義する必要はありません。 「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;
}

上記のコメントで指摘されているように、これはテンプレートのこのインスタンス化を区別します。そして、あなたが持っていた質問に直接答えるために、テンプレートのインスタンス化でテンプレート引数の性質を指定することを「詳細な型指定子」と呼びます。

41
Robert Prévost

以下と同じです:

class roman;

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

つまり、class T型名が必要な場合、最初にTがクラスの名前であることを宣言してから、残りの式に使用される型名としてTに進みます。

C++では、型名romanとここで宣言されている変数名romanの間に衝突がないことに注意してください。それは許可されています。


この別のケースは、テンプレートなしで発生する可能性があります。例:

void func( class bar *ptr );

barが宣言されていない場合は正しいです。 barを宣言してから、barへのポインターを取る関数を宣言します。

27
M.M