在C++ 11中,可变参数模板允许用任意数量的参数调用函数,并且省略号运算符...允许该可变参数函数对每个参数执行某些操作,即使每个参数的某些内容不同:
template<typename... Types>
void dummy(Types... ts){} //dummy to allow function calls via parameter expansion
template<typename... Numerics>
void increment5(Numerics&... ns){
dummy(ns+=5 ...); //parameter expansion (need space after 5 because 5. is decimal)
//it means "dummy(ns_first+=5, ns_second+=5, ns_third+=5, etc.)"
}
int main(){
int i = 0;
float f = 1.1;
std::valarray<int> vi = {1,2,3};
increment5(i,f,vi);
cout
<<i<<endl
<<f<<endl
<<vi[0]<<' '<<vi[1]<<' '<<vi[2]<<endl;
}
Run Code Online (Sandbox Code Playgroud)
如果我们定义一个异构值数组(不同数字类型的列表),我们希望能够做同样的事情(能够为每个元素添加一个数字).但我们必须将元素存储为元组.
//a class of numbers, possibly different
template<typename... Numerics>
class HeterogeneousValueArray{
private:
tuple<Numerics...> inner;
public:
//initialize the internal vector
HeterogeneousValueArray(Numerics... ns): inner(ns...) {}
};
//Given this function, we don't have to explicitly give the types
//when constructing a HVA
template<typename... Numerics>
HeterogeneousValueArray<Numerics...> HeterogeneousValueArray(Numerics... ns){
return HeterogeneousValueArray<Numerics...>(ns);
}
Run Code Online (Sandbox Code Playgroud)
要调用上面的increment5运算符,我们需要进行元组扩展.据我了解,这个解决方案需要为我想写的每个函数定义辅助函数.我们也可以递归地定义increment5,但是,每个函数需要两个函数体.
我相信编程语言应该努力设计,允许我们编写我们想要编写的代码.所以这就是我想写的.
template<typename... Numerics>
void increment5(HeterogeneousValueArray<Numerics...>& hva){
increment5(hva.inner... ); //expand a tuple
}
Run Code Online (Sandbox Code Playgroud)
或这个.
template<typename... Numerics>
void increment5(HeterogeneousValueArray<Numerics...>& hva){
dummy((hva.inner+5)... ); //expand a tuple
}
Run Code Online (Sandbox Code Playgroud)
换句话说,我想将元组视为参数包.
当然,"编写您想要编写的代码"是理想主义的,并且实现任何功能都可能存在问题.什么样的问题会使这种功能无法正常工作(歧义?),或者它如何踩到现有代码或功能的脚趾?或者......它是否已经存在于C++ 14中?
创建解决方案的基本工具存在于C++ 14中,但您需要通过额外的辅助函数实现额外的间接级别,类似于您链接到的答案:
template<typename Tuple, std::size_t... I>
void
_increment5(Tuple& t, std::index_sequence<I...>)
{
dummy( std::get<I>(t) += 5 ... );
}
template<typename... Numerics>
void
increment5(HeterogeneousValueArray<Numerics...>& hva)
{
_increment5(hva.inner, std::index_sequence_for<Numerics...>());
}
Run Code Online (Sandbox Code Playgroud)
std::index_sequence_for<T1, T2, T3>是类型的别名std::index_sequence<0, 1, 2>,因此当与包扩展一起使用时,它会为参数包的元素创建一系列索引.然后可以通过辅助函数推断该索引序列作为另一个参数包,因此包扩展std::get<I>(t)...将扩展I以提取元组的每个元素.
添加index_sequence到C++ 14 的提议还添加了一个示例,显示了apply将函数对象应用于元组的通用函数,这将允许@DyP在上面的注释中建议:
template<typename... Numerics>
void
increment5(HeterogeneousValueArray<Numerics...>& hva)
{
apply(hva.inner, [](auto& n) { n += 5; });
}
Run Code Online (Sandbox Code Playgroud)
该apply函数不在C++ 14中(但已经为C++ 17 提出),因此您需要自己编写,例如通过从C++ 14草案中复制它.
最接近直接允许你想要的东西是N3728,但是还没有被接受,所以不会在C++ 14中.
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |