最好的方法是使注册函数的代码位在其参数和返回类型上成为模板。然后,您可以将其拆开并返回一个 lambda,该 lambda 知道如何解析 XML 并调用该函数。真正的 hacky 概念证明 [它不处理 varargs(硬编码为 2),使用字符串而不是 xml,假设类型是默认可构造的,不处理 refs 或移动,并且给读者留下了很多练习] 是:
#include <string>
#include <functional>
#include <sstream>
#include <iostream>
#include <stdexcept>
template<class FIRST, class SECOND, class RETURN_TYPE>
std::function<RETURN_TYPE(std::string const&)> RegisterFunction(
RETURN_TYPE(func)(FIRST f, SECOND s))
{
auto copy = *func;
return[copy](std::string const& str)->RETURN_TYPE
{
std::istringstream inStream(str);
FIRST f;
inStream >> f;
if(inStream.fail())
{
throw std::runtime_error("Couldn't parse param one");
}
SECOND s;
inStream >> s;
if(inStream.fail())
{
throw std::runtime_error("Couldn't parse param two");
}
// can check if inStream is eof here for consistency
return copy(f, s);
};
}
std::string MyFunc(float f, std::string s)
{
std::ostringstream os;
os << "MyFunc called with float " << f << " and string " + s;
return os.str();
}
int main()
{
auto wrapper = RegisterFunction(MyFunc);
// Now try to call it
std::cout << wrapper("42.0 HelloWorld") << std::endl;
// Try to call it with an invalid string
try
{
std::cout << wrapper("This isn't the number you are looking for");
}
catch(...)
{
std::cout << "Failed to call function" << std::endl;
}
}
输出:
MyFunc called with float 42 and string HelloWorld
Failed to call function