我想编写一个模板函数来执行此操作(伪代码):
shift(T& a,T& b,T& c,...,T& y,const T& z) {
a = b;
b = c;
...
y = z;
}
我的尝试涉及将可变参数作为第一个参数,如下所示:
template<typename A, typename B>
inline void shift(A& a, const B& b) noexcept {
a = b;
}
template<typename B, typename C, typename... AA>
inline void shift(AA&... aa, B& b, const C& c) noexcept {
shift(aa...,b);
shift(b,c);
}
为什么这行不通?可变参数只能是最后一个参数吗?那有没有办法让最后一个引用常量呢?
我需要一个 const
引用,例如:
double a, b, c;
shift(a,b,c,5);
编辑: 好的,这个特殊问题当然可以通过颠倒函数参数的顺序来解决:
template<typename A, typename B>
inline void shift(const B& b, A& a) noexcept {
a = b;
}
template<typename C, typename B, typename... AA>
inline void shift(const C& c, B& b, AA&... aa) noexcept {
shift(b,aa...);
b = c;
}
但我仍然想知道语法是否允许将可变参数放在最后一个以外的任何地方,以及在什么情况下?
最佳答案
正如 T.C. 下面的评论所指出的,在您的第一个示例中 aa
处于非推导上下文中(14.8.2.5 p5 定义了非推导上下文,包括“一个函数参数包没有出现在参数声明列表的末尾”),因此无法推导出参数包。
if syntax allows for placing variadic arguments in any place other then the last and under what circumstances?
除了上述导致第一个示例出现问题的限制外,模板参数包必须是最后一个模板参数,除非可以推导出所有后续模板参数。 14.1 [温度参数] p11:
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2).
所以这是可以的,因为两个模板参数包都可以独立于函数参数推导:
template<typename... T, typename... U>
void f(std::tuple<T...>, std::tuple<U...>)
{ }
另一种编写 shift
函数的方法是使用 index_sequence
#include <tuple>
#include <iostream>
template<typename... T, size_t... I>
void
shift_impl(std::tuple<T...> t, std::index_sequence<I...>)
{
// Use pack expansion with comma operator to populate unused array:
int dummy[] = {
(std::get<I>(t) = std::get<I+1>(t), 0)...
};
}
template<typename T0, typename... T>
void
shift(T0&& arg0, T&&... args)
{
shift_impl(std::tie(arg0, args...), std::index_sequence_for<T...>{});
}
int main()
{
int i = 0, j = 1, k = 2;
shift(i, j, k);
std::cout << i << ' ' << j << ' ' << k << '\n';
}
关于c++ - 向后可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33661847/