使用参数包扩展调用具有可变参数的函数,但修改第i个参数

0xb*_*00d 5 c++ variadic-functions variadic-templates c++11

假设我们有一个功能

template<typename T, typename... Args>
T f(Args... args);
Run Code Online (Sandbox Code Playgroud)

我们想要调用f另一个函数

template<typename... Args>
void bar(Args... args) {
    // f(args1, ..., args(i-1), "modified argsi", args(i+1), ..., argsn);
}
Run Code Online (Sandbox Code Playgroud)

i为所有人修改-th参数(并保持其他参数不变)i = 1, ..., n.f将返回一个结果,我想将所有n结果存储在一个valarray.

我们怎么做?

Jar*_*d42 3

使用I编译时值,您可以执行以下操作:

namespace detail
{

    template<std::size_t I>
    struct impl
    {
        template <typename TUPLE>
        auto operator() (TUPLE&& t) { return std::get<I>(t); }
    };

    template<>
    struct impl<2>
    {
        template <typename TUPLE>
        auto operator() (TUPLE&& t) { return std::get<2>(t) + 40; }
    };

    template <std::size_t... Is, typename TUPLE>
    void bar(std::index_sequence<Is...>, TUPLE&& Tuple) {
        return f(impl<Is>{}(std::forward<TUPLE>(Tuple))...);
    }

}

template<typename... Args>
void bar(Args... args) {
    detail::bar(std::index_sequence_for<Args...>(), std::forward_as_tuple(args...));
}
Run Code Online (Sandbox Code Playgroud)

现场演示

具有i运行时值:

namespace detail
{

    template<class T>
    auto modifier(T&& arg, std::size_t i, std::size_t pos) {
        if (i == pos)
            return arg + 40; // Or appropriate modification.
        else
            return std::forward<T>(arg);
    }

    template <std::size_t... Is, typename... Args>
    void bar(std::size_t pos, std::index_sequence<Is...>, Args&&... args) {
        return f(modifier(std::forward<Args>(args), Is, pos)...);
    }

}

template<typename... Args>
void bar(std::size_t pos, Args&&... args) {
    detail::bar(pos, std::index_sequence_for<Args...>(), std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

现场演示