不同类型的助推功能图?

时间:2009-03-14 21:10:29

标签: c++ boost

我想知道在C ++中是否有办法做到这一点?

void func1(const std::string& s)
{
std::cout << s << std::endl;
}

void func2(int me)
{
std::cout << me << std::endl;
}

int main()
{
std::map<std::string, boost::function< ??? > > a_map;

a_map["func1"] = &func1;
a_map["func1"]("HELLO");

}

有没有办法在上面使用boost功能和地图做什么?

6 个答案:

答案 0 :(得分:2)

您可能无法使用std::map,因为它是一个同质的容器。尝试,例如boost::variant(他们支持访客模式)或boost::tuple

答案 1 :(得分:2)

有一些方法来存储函数,问题是,为了能够使用所需的参数调用函数,你必须知道函数的调用签名,如果你有这些信息,你不妨使用单独的地图,或使用比boost :: function更复杂的对象。

如果你愿意做一些工作并拥有有限数量的签名,你可以这样做:

class MultiFunc
{
protected:
    MultiFunc() {}

public:
    typedef void (*stringFunc)(const std::string&);
    typedef void (*intFunc)(int);

    static MultiFunc *Create(stringFunc function);
    static MultiFunc *Create(intFunc function);

    virtual void operator()(const string &) { throw exception(); }
    virtual void operator()(int) { throw exception(); }
    virtual ~MultiFunc();
};

class MultiFuncString : public MultiFunc
{
private:
    stringFunc Function;
public:
    MultiFuncString(stringFunc function) : Function(function) {}
    virtual void operator()(const string &arg) { Function(arg); }
};

class MultiFuncInt : public MultiFunc
{
private:
    intFunc Function;
public:
    MultiFuncInt(intFunc function) : Function(function) {}
    virtual void operator()(int arg) { Function(arg); }
};

MultiFunc *MultiFunc::Create(MultiFunc::stringFunc function)
{
    return new MultiFuncString(function);
}
MultiFunc *MultiFunc::Create(MultiFunc::intFunc function)
{
    return new MultiFuncInt(function);
}

void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}

int main()
{
    map<string, MultiFunc *> a_map;
    a_map["func1"] = MultiFunc::Create(&func1);
    (*a_map["func1"])("Hello");
    a_map["func2"] = MultiFunc::Create(&func2);
    (*a_map["func2"])(3);

    // Remember to delete the MultiFunc object, or use smart pointers.
}

输出:

Hello
3

不幸的是,你不能制作模板化的虚函数,或者你很容易将这一切都概括。

答案 2 :(得分:2)

你要做的事听起来有点奇怪。通常,您将使容器成为具有相同签名的抽象类型或对象或函数的集合。否则,在迭代容器时,您如何知道如何调用该函数?我喜欢使用已知签名使容器成为函数对象的集合,然后使用Boost.Bind存储使用其他参数调用函数的闭包。

例如:

typedef boost::function<void, void> Function;
typedef std::map<std::string, Function> Functions;

Functions functions:

void foo()
{
  ...
}

functions["foo"] = foo;

void bar(std::string &s)
{
  ...
}

// binds the value "hello" to the s parameter
functions["bar"] = boost::bind(bar, "hello");

答案 3 :(得分:0)

请阅读以下链接。它讨论了使用boost :: bind来存储std :: map

中的函数指针

http://www.gamedev.net/community/forums/topic.asp?topic_id=526381&whichpage=1&#3411515

答案 4 :(得分:0)

存储接口:

struct IStringData
{
    virtual std::string get() const = 0;
    virtual ~IStringData() {}
};

并制作实现,一个只保存字符串值,其他实现将存储仿函数,也许你将来会有其他实现。

答案 5 :(得分:0)

没有。你不能。因为boost :: function不是多态的,所以它在那里分解。 (它需要一组固定的参数类型。)

但是,有人谈到在升级邮件列表上朝这个方向开展的工作,所以请搜索档案,看看是否有一些代码可以使用。

解决方法是使用boost :: function,但是你需要向地图添加不是你的真实函数(即func1 / func2),而是从任意容器中提取类型并调用实际函数的调度函数。 (并且如果它错了就保释,就像在任何动态的语言中一样。)