5

テンプレート引数の演繹が実際にどのように機能するかについての優れた説明は得られていないため、次のように動作を説明する方法がわかりません。

template<typename T>
struct Base
{
protected:
    template<bool aBool = true>
    static void Bar(int)
    {
    }
};

template<typename T>
class Derived : public Base<T>
{
public: 
    void Foo() { Base<T>::Bar<false>(5); } 
};

int main()
{
    Derived<int> v;
    v.Foo();
    return 0;
}

このコードはビルドされず、エラーが発生します。

main.cpp: In instantiation of 'void Derived<T>::Foo() [with T = int]':
main.cpp:25:8:   required from here main.cpp:19:15: error: invalid
operands of types '<unresolved overloaded function type>' and 'bool'
to binary 'operator<'

Base<T>Derivedの2をに変更するとBase<int>、コンパイルされます。呼び出しをBar()に変更するとBase<T>::template Bar<false>(5);、コンパイルも行われます。

これについての説明として私が見たワンライナーは、コンパイラがBarがテンプレートであることを知らないということです。おそらく、Derivedの特殊化が宣言されるまで、Baseが何であるかを知らないためです。ただし、コンパイラがのコードの生成を開始するとFoo()Base<T>はすでに定義されており、のタイプをBar判別できます。コンパイラがシンボルがテンプレートでBarないoperator<()と想定し、代わりに適用しようとしている原因は何ですか?

コンパイルプロセスでテンプレートが評価されるときのルールに関係していると思います-私が探しているのは、このプロセスの優れた包括的な説明であり、次に次のようなコードに遭遇したときに、スタックオーバーフローの善良な人々の助けなしに答えを推測することができます。

c++x11をサポートするg++4.7でコンパイルしていることに注意してください。

4

1 に答える 1

3
void Foo() { Base<T>::Bar<false>(5); } 

このコンテキストでBase<T>は、依存する名前です。template依存名のメンバーテンプレートにアクセスするには、キーワードを追加する必要があります。

void Foo() { Base<T>::template Bar<false>(5); } 

それ以外の場合Base<T>::Barは、非テンプレートメンバーおよび未満<として解析されます。

が必要な理由templateは、2フェーズルックアップです。エラーは、型が置換される前の最初のパスでトリガーされるため、コンパイラーはの定義が何であるかを認識しませんBase<T>。たとえば、テンプレート以外のメンバー(たとえばメンバー)を持つforBarのスペシャライゼーションを追加したとします。に代入する前に、コンパイラはその型に特殊化があるかどうかを知りません。intBarintTFoo

于 2012-10-11T21:00:15.673 に答える