5

私は単純なクラスを持っておりA、可変引数関数テンプレートを提供しています。この関数は 内のプライベート データを使用しますAが、関数自体はパブリックです。クラスは次のようになります。

class A {
public:

    A() :
    _bla("bla: ") {
    }

    template <class T>
    void bar(const T& value) {
        std::cout << _bla << value << std::endl;
    }

    template <class H, class... T>
    void bar(const H& value, const T&... data) {
        std::cout << _bla << value << std::endl;
        bar(data...);
    }

private:
    const std::string _bla;
};

foo.hppという名前の別のファイルには、引数としてfoo()関数を受け取って使用できる関数があります。a.bar()

int main(int argc, char *argv[]) {    
    A a;
    a.bar(1, "two", 3, 4);
    foo(&a.bar);
}

どこから始めればよいかよくわかりませんが、次のことを試しましたが、うまくいきません。どうすれば正しくできますか:

template <typename... T>
inline void foo(void (bar *)(const T&...)) {
    unsigned int x(0), y(0), z(0);
    bar(x, y, z);
}

おまけの質問:だけでなく呼び出す方法はありますか:

foo(&a.bar);

foo次のようないくつかのパラメーターにa.barバインドして呼び出すこともできます。

foo(&(a.bar(p1, p2));

次のように、定義自体にp1andp2を追加するだけです。foo

foo(p1, p2, &a.bar);

しかし、これらのパラメーターを前に追加できれば、私の目的にとって意味的には良いでしょう。

4

1 に答える 1

9

インスタンス化せずに関数テンプレートのアドレスを渡すことはできません。これは、オーバーロード セット全体として扱われるためです (テンプレートが可変長であるかどうかに関係なく)。ただし、汎用ファンクターでラップすることはできます。

struct bar_caller
{
    template<typename... Ts>
    void operator () (A& a, Ts&&... args)
    {
        a.bar(std::forward<Ts>(args)...);
    }
};

次に、関数foo()を次のように定義します。

template<typename F>
inline void foo(A& a, F f) {
    unsigned int x(0), y(0), z(0);
    f(a, x, y, z);
}

したがって、関数呼び出しは次のmain()ようになります。

int main()
{
    A a;
    a.bar(1, "two", 3, 4);
    foo(a, bar_caller());
}

残念ながら、現時点では C++ でオーバーロード セットをファンクタに別のクラスを定義せずに簡単にラップする方法はありませんbar_caller

編集:

Aオブジェクトを に直接渡したくない場合でも、関数を呼び出さなければならないオブジェクトへの参照をカプセル化するfoo()ことができます(オブジェクトの有効期間に注意してください。そうすれば、参照がぶら下がりません)。 ):bar_callerAbar()

struct bar_caller
{
    bar_caller(A& a_) : a(a_) { }

    template<typename... Ts>
    void operator () (Ts&&... args)
    {
        a.bar(std::forward<Ts>(args)...);
    }

    A& a;
};

foo()その後、main()次のように書き換えることができます。

template<typename F>
inline void foo(F f) {
    unsigned int x(0), y(0), z(0);
    f(x, y, z);
}

int main()
{
    A a;
    a.bar(1, "two", 3, 4);
    foo(bar_caller(a));
}
于 2013-05-06T15:30:58.463 に答える