1

C++

(関数オブジェクト) クラス (バリアディック) テンプレートを介して関数ラッパーを実装しようとしています。このクラスは、唯一のデータ メンバとして、ラップしている関数ポインタによって初期化されるか割り当てられた関数ポインタを持っています。パラメーター化されたコンストラクターは、関数ポインターを受け取り、それによってメンバーを初期化します。operator()メソッドは引数を取り (またはなし)、ラップされた関数を呼び出します。少なくともそれがアイデアです。多くのエラーが発生するので、コメントでマークします。VC11 (2012 年 11 月の CTP で、可変個引数テンプレートを有効にする) はerror C2091: function returns function、マークされた領域の 1 つを除くすべてで私を与えてくれます。最後のエラーは異なります。コード内でその完全な説明をコメントします。g++ では、コード番号が異なりますが、ほとんど同じエラーが発生します。

#include <iostream>

template <typename R, typename... Tn>
class func
{
    R (*fptr)(Tn...); // C2091
public:
    func() : fptr(nullptr) {}
    func( R (*f) (Tn...) ) : fptr(f) {} // C2091
    R operator()(Tn... args)
    { // C2091
        return fptr(args...);
    }
    func& operator=( R (*f) (Tn...) ) // C2091
    {
        fptr = f;
        return *this;
    }
};

int foo(int a, int b)
{
    std::cout << "foo\n";
    return 0;
}

int main()
{
    func<int(int, int)> myfunc;
    myfunc = foo; // C2679: binary '=' : no operator found which takes
    // a right-hand operand of type 'int (__cdecl *)(int,int)' (or 
    // there is no acceptable conversion)
}

これらのエラーが発生するのはなぜですか? たとえば、パラメーター化されたコンストラクターが何かを返す方法や、データ メンバーの宣言が何かを返す方法がわかりません。データメンバ宣言が関数ポインタ宣言になっていませんか? たとえば、を受け取って?を返すint (*g)(int);関数を指すポインターを宣言しません。intint

編集/補遺:

答えからわかるのは、それint(int, int)は 1 つのタイプのみであり、目的の効果を得るには部分的な特殊化が必要であるということです。しかし、私のコードでエラーが発生するのは何ですか? コメントアウトしてmyfunc = fooも、他のエラーが発生します。func<int(int, int)> myfunc;デフォルトのコンストラクターを呼び出します。typename Rにインスタンス化されint(int, int)typename... Tn空になります。データ メンバは にR (*fptr)(Tn...);なるためR (*fptr)();fptr引数を 0 とって を返す関数を指す関数ポインタになりますRRint(int, int)の場合R、関数ポインタ型ですか、それとも関数型ですか? 後者の場合、エラー メッセージのコンテキストを理解できます。

4

3 に答える 3

2

部分的な専門化が必要です。

これが実際の例です:

template <typename T>
class func;

template <typename R, typename... Tn>
class func<R(Tn...)> {
    typedef R (*fptr_t)(Tn...);
    fptr_t fptr;
public:
    func() : fptr(nullptr) {}
    func(fptr_t f) : fptr(f) {}
    R operator()(Tn... args) {
        return fptr(args...);
    }
    func& operator=(fptr_t f) {
        fptr = f;
        return *this;
    }
};
于 2013-10-31T00:02:42.200 に答える
2

クラスは、戻り値と引数の型によってパラメーター化され、個別に記述されます。ただし、インスタンス化するときは、関数型 a la でパラメーター化しようとしますstd::function。それを作るfunc<int, int, int> myfunc;。この変更により、コードが機能します。

于 2013-10-30T23:55:26.653 に答える
2

int(int, int)シングルタイプです。そのように渡してラップを解除したい場合は、部分的な特殊化が必要です。

template <typename> struct func;         // leave undefined

template <typename R, typename ...Args>
struct func<R(Args...)>                  // specialized for typename = R(Args...)
{
    // ...
};
于 2013-10-30T23:59:29.120 に答える