如何在C++中围绕任意函数创建字符串参数化包装器

How to create a string-parameterized wrapper around an arbitrary function in C++?

本文关键字:字符串 创建 参数 包装 函数 任意 C++      更新时间:2023-10-16

我想以这样的方式生成包装器,以便为任意函数

R func(A a, B b, ...)

std::function<std::string (std::vector<std::string>)>

返回,它包装f,以便参数从向量中获取并(尝试(使用 boost::lexical_cast 进行转换,返回值相同。例如:

int add(int a, int b);
auto f = magic_wrap(&add);
auto result = f(std::vector<std::string>{"2", "3"});
// result == "5"

我的直觉告诉我,这应该可以通过可变参数模板来实现,但我坚持获取函数的返回和参数类型。这是否可能,如果是,如何?

我对boost::lexical_cast一无所知,但我认为这应该有效:

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 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);
        return boost::lexical_cast<std::string>(result);
    }
private:
    template<std::size_t... Is>
    R invoke(index_sequence<Is...>, std::vector<std::string> const& args)
    {
        return func_(boost::lexical_cast<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);
}

您可以在此处查看略微修改的版本(不使用 Boost(的工作演示。