C++ 使用参数包展开调用具有可变参数的函数,但修改第i-th个参数

C++ 使用参数包展开调用具有可变参数的函数,但修改第i-th个参数,c++,c++11,variadic-templates,variadic-functions,C++,C++11,Variadic Templates,Variadic Functions,假设我们有一个函数 template<typename T, typename... Args> T f(Args... args); 并修改所有i=1,…,n的i-th参数(其他参数保持不变)f将返回一个结果,我想将所有n结果存储在valarray中 我们如何才能做到这一点?使用I编译时值,您可以执行以下操作: namespace detail { template<std::size_t I> struct impl { t

假设我们有一个函数

template<typename T, typename... Args>
T f(Args... args);
并修改所有
i=1,…,n
i
-th参数(其他参数保持不变)
f
将返回一个结果,我想将所有
n
结果存储在
valarray


我们如何才能做到这一点?

使用
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...));
}

根据你的评论,我认为(?)你想要的是:

namespace detail {
    template <typename Arg, typename Idx>
    auto modify_arg(Arg&& arg, Idx )
    {
        // TODO: whatever modifications you want to make
        // to the argument indexed by Idx
    }

    template <size_t... Is, typename... Args>
    void bar(std::index_sequence<Is...>, Args&&... args) 
    {
        // Don't know where 'T' comes from - you still
        // need that for your f()
        f(modify_arg(std::forward<Args>(args),
                     std::integral_constant<size_t, Is>{})...
                     );
    }
}

template<typename... Args>
void bar(Args&&... args) {
    detail::bar(std::index_sequence_for<Args...>{},
                std::forward<Args>(args)...
                );
}
名称空间详细信息{
模板
自动修改参数(参数和参数,Idx)
{
//TODO:无论你想做什么修改
//指向由Idx索引的参数
}
模板
空栏(标准::索引_序列,参数和参数)
{
//不知道“t”来自哪里-你还是
//你的f()需要这个
f(修改参数(std::forward(参数),
std::积分_常数{})。。。
);
}
}
模板
空栏(Args&&…Args){
详细信息::条(std::索引序列{},
标准::转发(args)。。。
);
}

如果要避免分支,查找表就可以完成这项工作。草图:

#include <tuple>
#include <utility>
#include <iostream>

void foo(std::string a, std::string b, std::string c) {
    std::cout << a << '|' << b << '|' << c;
}

template <typename, typename> struct passerAux;
template <std::size_t... prevI, std::size_t... followI>
struct passerAux<std::index_sequence<prevI...>, std::index_sequence<followI...>> {
    template <typename... Args>
    static decltype(auto) passer( Args&&... args ) {
        auto tuple = std::forward_as_tuple(std::forward<Args>(args)...);
        return foo( std::forward<std::tuple_element_t<prevI, decltype(tuple)>>(std::get<prevI>(tuple))...,
                    "ModifiedArg",
                    std::forward<std::tuple_element_t<followI+sizeof...(prevI)+1, decltype(tuple)>>(std::get<followI+sizeof...(prevI)+1>(tuple))... );
    }
};

template <typename... Args, std::size_t... indices>
decltype(auto) passer( std::size_t i, std::index_sequence<indices...>, Args&&... args ) {
    void(*lookup[])(Args&&...) {
        passerAux<std::make_index_sequence<indices>, std::make_index_sequence<sizeof...(Args)-indices-1>>::passer...
    };
    return lookup[i](std::forward<Args>(args)...);
}

template <typename... Args>
decltype(auto) passer( std::size_t i, Args&&... args ) {
    return passer(i, std::make_index_sequence<sizeof...(Args)>{}, std::forward<Args>(args)... );
}

int main() {
    passer(0, "A", "B", "C"); std::cout << '\n';
    passer(1, "A", "B", "C"); std::cout << '\n';
    passer(2, "A", "B", "C");
}
#包括
#包括
#包括
void foo(标准::字符串a、标准::字符串b、标准::字符串c){

std::cout非编译时实现可能是:

#include <iostream>
#include <type_traits>

// Replace a value at a position
// =============================

template<typename R>
struct Replace {
    int i;
    R replacement;
    Replace(int i, R&& replacement)
    :   i(i), replacement(replacement)
    {}

    template<typename T>
    T&& operator() (T&& value) noexcept {
        return (0 == i--)
            ? std::forward<T>(replacement)
            : std::forward<T>(value);
    }
};

template <typename R, typename... Args>
Replace<R> replace(int i, R&& replacement) {
    return Replace<R>(i, std::forward<R>(replacement));
}

// Test: Print values
// ==================

template<typename T, typename... Args>
void print(const T&, const Args&...);

template<typename T, typename... Args>
void print(const T& value) {
    std::cout << value << '\n';
}

template<typename T, typename... Args>
void print(const T& value, const Args&... args) {
    std::cout << value << '\n';
    print(args...);
}


// Test: Function
// ==============

template<typename... Args>
void f(Args... args) {
    // Note, 'print(replace(1, 7)(args)...);' will not work.
    auto r = replace(1, 7);
    print(r(args)...);
}


int main()
{
    f(1, 2, 3);
}
#包括
#包括
//替换某个位置的值
// =============================
模板
结构替换{
int i;
R置换;
替换(int i、R和替换)
:i(i),替换(替换)
{}
模板
T&&运算符()(T&&值)无异常{
返回值(0==i--)
?标准:正向(替换)
:std::forward(值);
}
};
模板
替换替换(int i、R和替换){
返回替换(i,标准::转发(替换));
}
//测试:打印值
// ==================
模板
无效打印(常量T和,常量参数和…);
模板
无效打印(常量T和值){

std::cout是编译时知道的还是只在运行时知道的?@0xbadf00d你没有回答这个问题-编译时还是运行时?i
来自哪里?但是变量模板的要点是,这个数字并不意味着什么。它可以有从0到无穷多个参数的任何东西。如果n实际上小于n,会发生什么我?@0xbadf00d呃。什么?那么你想调用
f
,修改所有
args…
,那么
T
从哪里来?你想对
f()
的结果做什么?@Barry实际上,我回答了这个问题。我们知道
n=sizeof…(args)
。我需要使用修改后的第I个参数调用f,对于所有I=1,…,您也可以使用三元运算符,而不是附加的函数+if子句。不确定是否更易于阅读:
void(*lookup[])(Args&&…
My eyes!D:
#include <tuple>
#include <utility>
#include <iostream>

void foo(std::string a, std::string b, std::string c) {
    std::cout << a << '|' << b << '|' << c;
}

template <typename, typename> struct passerAux;
template <std::size_t... prevI, std::size_t... followI>
struct passerAux<std::index_sequence<prevI...>, std::index_sequence<followI...>> {
    template <typename... Args>
    static decltype(auto) passer( Args&&... args ) {
        auto tuple = std::forward_as_tuple(std::forward<Args>(args)...);
        return foo( std::forward<std::tuple_element_t<prevI, decltype(tuple)>>(std::get<prevI>(tuple))...,
                    "ModifiedArg",
                    std::forward<std::tuple_element_t<followI+sizeof...(prevI)+1, decltype(tuple)>>(std::get<followI+sizeof...(prevI)+1>(tuple))... );
    }
};

template <typename... Args, std::size_t... indices>
decltype(auto) passer( std::size_t i, std::index_sequence<indices...>, Args&&... args ) {
    void(*lookup[])(Args&&...) {
        passerAux<std::make_index_sequence<indices>, std::make_index_sequence<sizeof...(Args)-indices-1>>::passer...
    };
    return lookup[i](std::forward<Args>(args)...);
}

template <typename... Args>
decltype(auto) passer( std::size_t i, Args&&... args ) {
    return passer(i, std::make_index_sequence<sizeof...(Args)>{}, std::forward<Args>(args)... );
}

int main() {
    passer(0, "A", "B", "C"); std::cout << '\n';
    passer(1, "A", "B", "C"); std::cout << '\n';
    passer(2, "A", "B", "C");
}
#include <iostream>
#include <type_traits>

// Replace a value at a position
// =============================

template<typename R>
struct Replace {
    int i;
    R replacement;
    Replace(int i, R&& replacement)
    :   i(i), replacement(replacement)
    {}

    template<typename T>
    T&& operator() (T&& value) noexcept {
        return (0 == i--)
            ? std::forward<T>(replacement)
            : std::forward<T>(value);
    }
};

template <typename R, typename... Args>
Replace<R> replace(int i, R&& replacement) {
    return Replace<R>(i, std::forward<R>(replacement));
}

// Test: Print values
// ==================

template<typename T, typename... Args>
void print(const T&, const Args&...);

template<typename T, typename... Args>
void print(const T& value) {
    std::cout << value << '\n';
}

template<typename T, typename... Args>
void print(const T& value, const Args&... args) {
    std::cout << value << '\n';
    print(args...);
}


// Test: Function
// ==============

template<typename... Args>
void f(Args... args) {
    // Note, 'print(replace(1, 7)(args)...);' will not work.
    auto r = replace(1, 7);
    print(r(args)...);
}


int main()
{
    f(1, 2, 3);
}