-1

テンプレートを使用してジェネリック関数マップを作成しようとしています。アイデアは、特定の関数ポインター型を持つこのジェネリックテンプレートクラスから継承することです。グローバルワークスペースに関数を登録することはできますが、派生クラスにすべての関数をまとめてコンストラクターに登録したいと思います。私はもうすぐここにいると思いますが、コンパイルエラーが発生します。これが私のコードの簡略版です:

#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std; 

int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);

// function factory
template <typename T>
class FunctionMap {
public: 
    void registerFunction(string name, T fp) {
        FunMap[name] = fp;
    }
    T getFunction(string name) {
        assert(FunMap.find(name) != FunMap.end());
        return FunMap[name];
    }
private:
    map<string, T> FunMap;
};

// specific to integer functions 
class IntFunctionMap : public FunctionMap<F> {
public:
    int f2(int x) { return 2 * x; }
    int g2(int x) { return -3 * x; }
    IntFunctionMap() {
        registerFunction("f", f); // This works
        registerFunction("f2", f2); // This does not
    }
};

int main()
{
     FunctionMap<F> fmap; // using the base template class directly works
     fmap.registerFunction("f", f);
     F fun = fmap.getFunction("f");
     cout << fun(10) << endl; 
     return 0;
}

私が得るエラーは次のとおりです。

templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to     ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]
4

1 に答える 1

0

Juanの答えは正しいです。メンバー関数には、メンバーであるタイプへのポインターである暗黙の最初のパラメーターがあります。コードのコンパイルに失敗する理由は、マップがタイプがの関数ポインターをサポートしているint (*)(int)が、タイプがf2であるためですint (IntFunctionMap::*)(int)

ここに示す特定のケースでは、std::function型の消去を実装するを使用して、無料の関数とメンバー関数を同じ型として表示できます。その後、あなたはあなたがやろうとしていることをすることができます。注:これにはC++11が必要です。

#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>

using namespace std; 

int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }

typedef std::function<int (int)> F;

// function factory
template <typename T>
class FunctionMap {
public: 
    void registerFunction(string name, T fp) {
        FunMap[name] = fp;
    }
    T getFunction(string name) {
        assert(FunMap.find(name) != FunMap.end());
        return FunMap[name];
    }
private:
    map<string, T> FunMap;
};

// specific to integer functions 
class IntFunctionMap : public FunctionMap<F> {
public:
    int f2(int x) { return 2 * x; }
    int g2(int x) { return -3 * x; }

    IntFunctionMap() {
        registerFunction("f", f); // This works
        registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
    }
};

int main()
{
     FunctionMap<F> fmap; // using the base template class directly works
     fmap.registerFunction("f", f);
     F fun = fmap.getFunction("f");
     cout << fun(10) << endl; 
     return 0;
}
于 2013-02-15T23:57:46.473 に答える