这是一个 C++11 解决方案。它不支持printall
像or之类的可变参数函数printf
,使用这种技术是不可能的,IMO 根本不可能,或者至少非常棘手。无论如何,这样的功能很难在像您这样的环境中安全使用,因为来自任何客户端的任何错误请求都可能使服务器崩溃,并且绝对没有任何追索权。您可能应该转向基于容器的界面以获得更好的安全性和稳定性。
另一方面,此方法统一支持所有(?)其他功能。
#include <vector>
#include <iostream>
#include <functional>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>
template <typename Ret, typename... Args>
Ret callfunc (std::function<Ret(Args...)> func, std::vector<boost::any> anyargs);
template <typename Ret>
Ret callfunc (std::function<Ret()> func, std::vector<boost::any> anyargs)
{
if (anyargs.size() > 0)
throw std::runtime_error("oops, argument list too long");
return func();
}
template <typename Ret, typename Arg0, typename... Args>
Ret callfunc (std::function<Ret(Arg0, Args...)> func, std::vector<boost::any> anyargs)
{
if (anyargs.size() == 0)
throw std::runtime_error("oops, argument list too short");
Arg0 arg0 = boost::any_cast<Arg0>(anyargs[0]);
anyargs.erase(anyargs.begin());
std::function<Ret(Args... args)> lambda =
([=](Args... args) -> Ret {
return func(arg0, args...);
});
return callfunc (lambda, anyargs);
}
template <typename Ret, typename... Args>
std::function<boost::any(std::vector<boost::any>)> adaptfunc (Ret (*func)(Args...)) {
std::function<Ret(Args...)> stdfunc = func;
std::function<boost::any(std::vector<boost::any>)> result =
([=](std::vector<boost::any> anyargs) -> boost::any {
return boost::any(callfunc(stdfunc, anyargs));
});
return result;
}
基本上你调用adaptfunc(your_function)
, whereyour_function
是任何类型的函数(可变参数除外)。作为回报,您将获得一个std::function
接受 的向量boost::any
并返回 的对象boost::any
。你把这个对象放在你的 中func_map
,或者对它们做任何你想做的事情。
在实际调用时检查参数的类型及其数量。
void
开箱即用不支持返回函数,因为boost::any<void>
不支持。这可以通过将返回类型包装在一个简单的模板中并专门针对void
. 为了清楚起见,我把它省略了。
这是一个测试驱动程序:
int func1 (int a)
{
std::cout << "func1(" << a << ") = ";
return 33;
}
int func2 (double a, std::string b)
{
std::cout << "func2(" << a << ",\"" << b << "\") = ";
return 7;
}
int func3 (std::string a, double b)
{
std::cout << "func3(" << a << ",\"" << b << "\") = ";
return 7;
}
int func4 (int a, int b)
{
std::cout << "func4(" << a << "," << b << ") = ";
return a+b;
}
int main ()
{
std::vector<std::function<boost::any(std::vector<boost::any>)>> fcs = {
adaptfunc(func1), adaptfunc(func2), adaptfunc(func3), adaptfunc(func4) };
std::vector<std::vector<boost::any>> args =
{{777}, {66.6, std::string("yeah right")}, {std::string("whatever"), 0.123}, {3, 2}};
// correct calls will succeed
for (int i = 0; i < fcs.size(); ++i)
std::cout << boost::any_cast<int>(fcs[i](args[i])) << std::endl;
// incorrect calls will throw
for (int i = 0; i < fcs.size(); ++i)
try {
std::cout << boost::any_cast<int>(fcs[i](args[fcs.size()-1-i])) << std::endl;
} catch (std::exception& e) {
std::cout << "Could not call, got exception: " << e.what() << std::endl;
}
}