3

の2つのオーバーロードがありますoperator()。1つは、パラメーターとして任意の型を取り、任意の型を返す関数参照を取ります。もう1つは、任意の型をパラメーターとして受け取るが、を返す関数参照を取りますvoid。クラスをインスタンス化すると、次のエラーが発生します。

In instantiation of 'A<void, int>':
error: 'void A<T, F>::operator()(void (&)(F)) [with T = void, F = int]' cannot be overloaded
error: with 'void A<T, F>::operator()(T (&)(F)) [with T = void, F = int]'

template <typename T, typename F> struct A {
    void operator()(T (&)(F)) {}
    void operator()(void (&)(F)) {}
};

void f(int) {}

int main() {

    A<void, int> a;
    a(f);
}

Tこれらのエラーは、最初のテンプレート引数が。の場合にのみ発生しますvoid。何が間違っているのか、なぜoperator()このようにオーバーロードできないのか知りたいのですが。

4

1 に答える 1

7

Tそうだとすればvoid、まったく同じプロトタイプを持つ2つの関数定義があります-ODRを壊します。

これを防ぐために、構造体を特殊化してみてください。

template <typename T, typename F> struct A {
    void operator()(T (&)(F)) {}
    void operator()(void (&)(F)) {}
};

template <typename F> struct A<void, F> {
    void operator()(void (&)(F)) {}
};
于 2012-12-23T13:39:40.437 に答える