これを行う最善の方法は、関数を登録するコードのビットをそのパラメーターと戻り値のテンプレートにすることです。次に、これを分解して、XML を解析して関数を呼び出す方法を知っているラムダを返すことができます。本当にハックな概念の証明 [varargs を処理せず (2 にハードコードされている)、xml の代わりに文字列を使用し、型がデフォルトで構築可能であると想定し、refs や move を処理せず、読者の演習として多くを残している] は、 :
#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