#include <cstddef>
#include <functional>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
template<std::size_t... Is>
struct index_sequence
{ };
template<std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...>
{ };
template<std::size_t... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...>
{ };
template<typename T>
T unstring(std::string const& s)
{
std::stringstream ss(s);
T result;
if (!(ss >> result)) {
throw std::logic_error("Cannot convert T into a string");
}
return result;
}
template<typename R, typename... Args>
class wrapped
{
public:
explicit
wrapped(R (&func)(Args...))
: func_(func)
{
}
public:
std::string operator()(std::vector<std::string> args)
{
if (sizeof...(Args) != args.size()) {
throw std::logic_error("Incorrect number of arguments");
}
auto const& result = invoke(make_index_sequence<sizeof...(Args)>(),
args);
using std::to_string;
return to_string(result);
}
private:
template<std::size_t... Is>
R invoke(index_sequence<Is...>, std::vector<std::string> const& args)
{
return func_((unstring<Args>)(args[Is])...);
}
private:
R (*func_)(Args...);
};
template<typename R, typename... Args>
std::function<std::string (std::vector<std::string>)>
wrap(R (&func)(Args...))
{
return wrapped<R, Args...>(func);
}
int add(int const x, int const y)
{
return x + y;
}
int main()
{
auto const f = wrap(add);
std::cout << f({"1", "2"});
}
I2luY2x1ZGUgPGNzdGRkZWY+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxzc3RyZWFtPgojaW5jbHVkZSA8c3RkZXhjZXB0PgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgoKdGVtcGxhdGU8c3RkOjpzaXplX3QuLi4gSXM+CnN0cnVjdCBpbmRleF9zZXF1ZW5jZQp7IH07Cgp0ZW1wbGF0ZTxzdGQ6OnNpemVfdCBOLCBzdGQ6OnNpemVfdC4uLiBJcz4Kc3RydWN0IG1ha2VfaW5kZXhfc2VxdWVuY2UgOiBtYWtlX2luZGV4X3NlcXVlbmNlPE4gLSAxLCBOIC0gMSwgSXMuLi4+CnsgfTsKCnRlbXBsYXRlPHN0ZDo6c2l6ZV90Li4uIElzPgpzdHJ1Y3QgbWFrZV9pbmRleF9zZXF1ZW5jZTwwLCBJcy4uLj4gOiBpbmRleF9zZXF1ZW5jZTxJcy4uLj4KeyB9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KVCB1bnN0cmluZyhzdGQ6OnN0cmluZyBjb25zdCYgcykKewogICAgc3RkOjpzdHJpbmdzdHJlYW0gc3Mocyk7CiAgICBUIHJlc3VsdDsKICAgIGlmICghKHNzID4+IHJlc3VsdCkpIHsKICAgICAgICB0aHJvdyBzdGQ6OmxvZ2ljX2Vycm9yKCJDYW5ub3QgY29udmVydCBUIGludG8gYSBzdHJpbmciKTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFIsIHR5cGVuYW1lLi4uIEFyZ3M+CmNsYXNzIHdyYXBwZWQKewpwdWJsaWM6CiAgICBleHBsaWNpdAogICAgd3JhcHBlZChSICgmZnVuYykoQXJncy4uLikpCiAgICAgICAgOiBmdW5jXyhmdW5jKQogICAgewogICAgfQoKcHVibGljOgogICAgc3RkOjpzdHJpbmcgb3BlcmF0b3IoKShzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4gYXJncykKICAgIHsKICAgICAgICBpZiAoc2l6ZW9mLi4uKEFyZ3MpICE9IGFyZ3Muc2l6ZSgpKSB7CiAgICAgICAgICAgIHRocm93IHN0ZDo6bG9naWNfZXJyb3IoIkluY29ycmVjdCBudW1iZXIgb2YgYXJndW1lbnRzIik7CiAgICAgICAgfQoKICAgICAgICBhdXRvIGNvbnN0JiByZXN1bHQgPSBpbnZva2UobWFrZV9pbmRleF9zZXF1ZW5jZTxzaXplb2YuLi4oQXJncyk+KCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MpOwogICAgICAgIHVzaW5nIHN0ZDo6dG9fc3RyaW5nOwogICAgICAgIHJldHVybiB0b19zdHJpbmcocmVzdWx0KTsKICAgIH0KCnByaXZhdGU6CiAgICB0ZW1wbGF0ZTxzdGQ6OnNpemVfdC4uLiBJcz4KICAgIFIgaW52b2tlKGluZGV4X3NlcXVlbmNlPElzLi4uPiwgc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IGNvbnN0JiBhcmdzKQogICAgewogICAgICAgIHJldHVybiBmdW5jXygodW5zdHJpbmc8QXJncz4pKGFyZ3NbSXNdKS4uLik7CiAgICB9Cgpwcml2YXRlOgogICAgUiAoKmZ1bmNfKShBcmdzLi4uKTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFIsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0ZDo6ZnVuY3Rpb248c3RkOjpzdHJpbmcgKHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPik+CndyYXAoUiAoJmZ1bmMpKEFyZ3MuLi4pKQp7CiAgICByZXR1cm4gd3JhcHBlZDxSLCBBcmdzLi4uPihmdW5jKTsKfQoKaW50IGFkZChpbnQgY29uc3QgeCwgaW50IGNvbnN0IHkpCnsKCXJldHVybiB4ICsgeTsKfQoKaW50IG1haW4oKQp7CglhdXRvIGNvbnN0IGYgPSB3cmFwKGFkZCk7CglzdGQ6OmNvdXQgPDwgZih7IjEiLCAiMiJ9KTsKfQo=