假设我们有一个功能
template<typename T, typename... Args>
T f(Args... args);
我们希望在其他功能中调用f
template<typename... Args>
void bar(Args... args) {
// f(args1, ..., args(i-1), "modified argsi", args(i+1), ..., argsn);
}
并修改所有i
的{{1}} - 参数(并保持其他参数不变)。 i = 1, ..., n
会返回结果,我希望将所有f
个结果存储在n
中。
我们怎么能这样做?
答案 0 :(得分: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...));
}
使用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)...);
}
答案 1 :(得分:1)
好吧,如果要避免分支,查找表就可以完成工作。粗略草图:
#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");
}
答案 2 :(得分:0)
根据您的评论,我认为(?)您想要的是:
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)...
);
}
答案 3 :(得分:0)
非编译时实现可能是:
#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);
}