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);
}