質問
友人と私は C++ テンプレートについて話し合っていました。彼は私に、これは何をすべきかを尋ねました。
#include <iostream>
template <bool>
struct A {
A(bool) { std::cout << "bool\n"; }
A(void*) { std::cout << "void*\n"; }
};
int main() {
A<true> *d = 0;
const int b = 2;
const int c = 1;
new A< b > (c) > (d);
}
main の最後の行には 2 つの適切な解析が含まれています。'b' はテンプレート引数ですか、それとも b > (c)
テンプレート引数?
これをコンパイルして何が得られるかを確認するのは簡単ですが、何がこの曖昧さを解決するのか疑問に思いました。
解決
私の知る限り、それは次のようにコンパイルされます new A<b>(c) > d
. 。これは私見ですが、それを解析する唯一の合理的な方法です。パーサーが通常の状況で > テンプレート引数の終了を想定できない場合、さらにあいまいさが生じます。逆にしたい場合は、次のように書く必要があります。
new A<(b > c)>(d);
他のヒント
Leon と Lee が述べているように、14.2/3 (C++ '03) ではこの動作を明示的に定義しています。
C++ '0x では、同様のルールが適用されてさらに楽しくなります。 >>
. 。基本的な概念は、テンプレート引数リストを解析するときに、ネストされていない引数リストを解析するということです。 >>
2 つの異なるものとして扱われます >
>
右シフト演算子ではなくトークン:
template <bool>
struct A {
A(bool);
A(void*);
};
template <typename T>
class C
{
public:
C (int);
};
int main() {
A<true> *d = 0;
const int b = 2;
const int c = 1;
new C <A< b >> (c) > (d); // #1
new C <A< b > > (c) > (d); // #2
}
上記の「#1」と「#2」は同等です。
もちろん、これにより、ネストされた特殊化にスペースを追加する必要がある煩わしさは修正されます。
C<A<false>> c; // Parse error in C++ '98, '03 due to "right shift operator"
C++ 標準では、テンプレート名の後に <
, 、 <
は常にテンプレート引数リストの先頭であり、ネストされていない最初の引数です。 >
は、テンプレート引数リストの最後とみなされます。
の結果を意図した場合は、 >
演算子がテンプレート引数である場合は、式を括弧で囲む必要があります。引数が引数の一部である場合は括弧は必要ありません。 static_cast<>
または別のテンプレート式。
おそらく、レクサーの貪欲さが、それを明示するための括弧の欠如の決定要因です。レクサーは貪欲ではないと思います。