-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 的回答是正确的:成员函数有一个隐式的第一个参数,它是指向它们所属类型的指针。您的代码无法编译的原因是您的映射支持具有 type 的函数指针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 回答