テンプレートクラスの構造体でのC ++コンパイラの問題


13

次のコードは、gccまたはclangでコンパイルできませ

template<class T>
class foo{};

template<class T>
class template_class_with_struct
{
    void my_method() {
        if(this->b.foo < 1);
    };

    struct bar
    {
        long foo;
    } b;
};

エラーメッセージは

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);

エラーはtemplatクラスfooが原因で発生します。<1の代わりに<=を書き込むと、コンパイルも行われます。

ヒントはありますか?

CompilerExplorerリンクhttps://godbolt.org/z/v6Tygo


7
私はコンパイラのバグを言うでしょうが、msvcがそれを受け入れる唯一のものです:-/ デモ。可能な回避策b.bar::fooまたは括弧((this->b.foo) < 1
Jarod42

回答:


1

GCCでは、

so.cpp:8:27: error: expected '>'
    if(this->b.foo < 1) 
                      ^

したがって、コンパイラーは、fooその行のがfoo上記のクラスを参照し、テンプレート引数を予期していると見なします。これはあなたが見ているものに似ています。

これをに変更すると<=、レクサーによって単一のトークンとしてトークン化されます。次のステージにはも表示<されないため、混乱することはありません。

inのlongと同じ名前を持たないようにクラスを変更した場合bar、この問題は発生しません。また、@ Jarod42はあなたの質問への彼のコメントに提案があります(より多くの資格または括弧)。

コンパイラーは段階的に作成され、各段階でコードが次の表現に変換され、各段階でその表現を使用してより複雑な処理を実行できます。

最初に、コンパイラーはコードを「字句解析」して、ファイル内の個々の文字をトークンのストリームに変換します。この行は次のようになります。

// if(this->b.foo < 1) 
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)

そして、それはに到達しますfoo。それはおそらくすべきです

- name(foo)
- operator(<)
- number(1)
- right-paren

しかし、それは私が見たときのように見えますfoo、それは前を見て<foo<class T>存在している事実を見て、それは単一のトークンを作り出そうとしますfoo< ...が、それ>を完了するために見つけることができません。

これは単なる推測です。名前を見つけてトークンを組み合わせることができる、字句解析器の前の段階である可能性があります。いずれにせよ、fooを複数回使用するとだまされます。


私はあなたの説明を理解しましたが、コンパイラがそのように振る舞うべきかどうかはわかりません。たぶん、これは別のコンパイラのバグとしてフィールドになるはずです。リンクされたライブラリヘッダー(cnt、count、counterなどの一般的な名前)内にどのテンプレートクラスがあるかを認識できない場合があります
eactor

それはバグだと思いますが、仕様が何を言っているのかわかりません。サードパーティヘッダーの名前が原因で問題が発生することは、C ++でよくあることです。通常は、資格で解決できます。
ルーフランコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.