1

テンプレート化されたC++クラスがあり、そのメンバー関数の1つにさらにテンプレートがあります。

私はそれを私のコードの2つの場所で呼んでいます。1つは機能し、もう1つは非常に紛らわしいエラーを生成します。これは以下のサンプルコードに要約されます。

#include <memory>

template <unsigned char N>
struct Foo
{
    template <typename OtherFoo, unsigned X>
    void do_work (
        const OtherFoo * __restrict,
        float,
        Foo * __restrict
        )
    const
    {
    }
};

struct Bar
{
    std :: unique_ptr <Foo<0>> foo_0;
    std :: unique_ptr <Foo<1>> foo_1;
    std :: unique_ptr <Foo<2>> foo_2;

    void run (float);

    template <typename FOO>
    void run (std :: unique_ptr <FOO> & foo, float x)
    {
        FOO out;
        foo -> template do_work <123> (foo_2.get(), x, &out);
    }
};

void Bar :: run (float x)
{
    if (foo_0)
        run (foo_0, x);
    else
        run (foo_1, x);
}

int main ()
{
    Bar bar;
    bar .run (1.23);
}

エラーメッセージは非常に単純ですが、明らかに間違っています。

temp.cpp: In member function ‘void Bar::run(std::unique_ptr<FOO>&, float) [with FOO = Foo<0u>]’:
temp.cpp:61:16:   instantiated from here
temp.cpp:54:3: error: no matching function for call to ‘Foo<0u>::do_work(Foo<2u>*, float&, Foo<0u>*)’
temp.cpp: In member function ‘void Bar::run(std::unique_ptr<FOO>&, float) [with FOO = Foo<1u>]’:
temp.cpp:63:16:   instantiated from here
temp.cpp:54:3: error: no matching function for call to ‘Foo<1u>::do_work(Foo<2u>*, float&, Foo<1u>*)’

見てみましょう、Foo<1u>::do_work(Foo<2u>*, float&, Foo<1u>*)...を呼び出すための一致する関数はありませんか?いいえ、それは私にはFoo::do_workの有効なインスタンス化のように見えます。

コンパイラは間違っていますか?(ubuntu12.04のgcc4.5.1)特に奇妙なのは、このコードがコードの他の場所で同等の呼び出しのように見えるものでコンパイルされることです(完全なものには依存関係が多すぎてここで意味のある再現ができません)。

4

1 に答える 1

2

関数テンプレートのテンプレートパラメータの順序を変更する必要があります。そうしdo_work<>()ないと、インスタンス化が実際に正しくなくなります。

//   template<typename OtherFoo, unsigned X> // This order is not appropriate.
                                             // Let template parameters that
                                             // cannot be deduced come first...
     template<unsigned X, typename OtherFoo>
     //       ^^^^^^^^^^  ^^^^^^^^^^^^^^^^^
     //       THIS FIRST      THEN THIS
     void do_work(const OtherFoo* __restrict, float, Foo* __restrict) const
     {
     }

これは、次の関数呼び出しで、最初のテンプレートパラメーターに明示的な引数を指定しているためです。

foo->template do_work<123>(foo_2.get(), x, &out);
于 2013-02-26T15:18:47.293 に答える