以下のコードは 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);
}
テンプレートへの引数は、使用するために必ずしも定義する必要はありません。 「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;
}
上記のコメントで指摘されているように、これはテンプレートのこのインスタンス化を区別します。そして、あなたが持っていた質問に直接答えるために、テンプレートのインスタンス化でテンプレート引数の性質を指定することを「詳細な型指定子」と呼びます。
以下と同じです:
class roman;
x3::rule<roman, unsigned> const roman = "roman";
つまり、class T
型名が必要な場合、最初にT
がクラスの名前であることを宣言してから、残りの式に使用される型名としてT
に進みます。
C++では、型名roman
とここで宣言されている変数名roman
の間に衝突がないことに注意してください。それは許可されています。
この別のケースは、テンプレートなしで発生する可能性があります。例:
void func( class bar *ptr );
bar
が宣言されていない場合は正しいです。 bar
を宣言してから、bar
へのポインターを取る関数を宣言します。