web-dev-qa-db-ja.com

テンプレート内のテンプレート:なぜ「 `>> 'はネストされたテンプレート引数リスト内で`>>'でなければならない」

別のテンプレート内でテンプレートを使用するときは、次のように記述する必要があることを知っています。

vector<pair<int,int> > s;

そして、空白なしで記述した場合:

vector<pair<int,int>> s;

エラーが発生します:

`>> 'は、ネストされたテンプレート引数リスト内の`>>'でなければなりません

これは理解できると思いますが、不思議に思わずにはいられません。どの場合、これは本当にあいまいになりますか?

49
zw324

時々want>>になります。検討する

boost::array<int, 1024>>2> x;

C++ 03では、これはサイズ256の配列を正常に解析して作成します。

あいまいになることはありません。これは、C++ 0xではテンプレートを閉じる間にスペースを書く必要がないという事実によって証明されています>sもう。

問題は、コンパイラが可能な限りコンテキストに依存しないで入力をトークン化することを好むということです。とにかくC++はコンテキストに依存しない言語ではないので、この1つの特別なケースだけを追加しても、物事が特に難しくなることはありません。

28
Armen Tsirunyan

現在の標準では、トークン化は貪欲であるため、>>a +++ bとして解析されるのと同じ方法で、a ++ + bは単一のトークンとして処理されます。これは変更され、新しい標準になりました。コンパイラーの実装者によるより多くの作業が必要ですが、全体的にはそれだけの価値があると見なされました(とにかく、一部の主要なコンパイラーはそれを拡張機能として既に実装しています)。

C++の解析は非常に難しく、他のほとんどの言語よりはるかに困難です。これは非常に一貫性のある言語ですが、入力のトークン化と構文の文法分析の理解との間で非常に多くの作業が行われるため、コンパイラーにとって単純であると思われることは多くの場合そうではありません。

歴史的な「>>」演算子は演算子です。ソースファイルがトークンに分割されるため、「識別」されます。これらのトークンは、文法分析中に(トークン化が完了してからかなり後)何らかのコンテキストで後で「理解」されます。

文法分析を行った場合whileトークン化すると、 ">>"がテンプレート宣言(または定義)の2つのクロージャーと見なされるべきであるという区別を支援する "ヘルプ"があります。しかし、これは歴史的に、C++コンパイラの歴史的な動作ではありません。 (新しいコンパイラーは、これらのあいまいさを解決するための「先読み」を含む、文法分析とトークン化の間でより多くのフィードバックを行います。)

はい。新しいC++ 0x標準が変更され、コンパイラベンダーは実装を書き直して、「>>」を明確にします。したがって、今後は曖昧になることはありません。ただし、古いC++コンパイラはこれを処理できないため、「>」文字の間のスペースとコードの互換性を維持することを「良い方法」と見なすことができます。

7
charley

適切なC++方言を設定して、このエラーを回避してください。たとえば、gcc 4.9では、次のファイルはg++でコンパイルされません。

#include <vector>
#include <utility>

int main()
{
    using namespace std;
    vector<pair<int, int>> v; // compile error!
    return 0;
}

物事の一番下に行きましょう:

#include <iostream>

int main()
{
    std::cout << __cplusplus << std::endl;
    return 0;
}

g++ test.cppだけでコンパイルされたこのコードは199711を出力します。gcc4.9は2014年にリリースされましたが、デフォルトのC++方言はC++ 98でGNU拡張機能です。 vector<pair<int, int> >vector<pair<int, int>>が必要な場合は、-std=c++11または-std=gnu++11を使用してさらにコンパイルします。

1

コンパイラに依存します。 Visual Studioはこれを強制しません。つまり、g ++がエラーを生成している間は両方が機能します。これはコンパイラの実装に依存すると思います。

1
iBrAaAa

ストリーム構文

cin >> var;

ネストされたテンプレートの構文

For<Bar<Barz>>

コンパイラの最初のフェーズでは、字句解析プログラムは認識できません。

0
Mani