car*_*ten 5 c++ templates vector
考虑以下(幼稚的)C ++代码段,将对象从自定义列表类型转换为 std::vector
template<class A> void transfer(std::vector<A>& target, const custom_list_type& source){
for(const A& elem:source){
target.push_back(elem);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,假设有人拥有一个std::vector
这样的自定义列表,并且想要展平结构或一个std::vector
这样的向量。天真的,我现在继续编写这种类型的函数。
template<class A> void flatten_transfer(std::vector<A>& target, const std::vector<custom_list_type>& source){
for(const auto& elem:source){
flat_transfer(target,elem);
}
}
template<class A> void flatten_transfer(std::vector<A>& target, const std::vector<std::vector<custom_list_type> >& source){
for(const auto& elem:source){
flat_transfer(target,elem);
}
}
Run Code Online (Sandbox Code Playgroud)
等等等等。但是我看到这不是很优雅,因为我需要每个深度级别的此功能的版本。我可以想象有一种使用一些模板魔术来解决此问题的更优雅的方法,但是我并不了解足够多的知识,无法提出真正更好的解决方案。
使用模板抽象出矢量深度级别的“推荐”方法是什么,从而只flatten_transfer
需要编写一个实例?
假设我正确理解了这个问题,以下函数模板在C ++ 17及更高版本中可以很好地实现此目的。target.push_back(elem)
当且仅当A
与相同时,此函数实例化B
。否则,将进入下一个深度:
template<
class A,
class B,
template <class...> class Container,
class... extras>
void flat_transfer(std::vector<A>& target, const Container<B, extras...>& source)
{
for(const auto& elem : source)
{
if constexpr(std::is_same<A, B>::value){
target.push_back(elem);
}
else{
flat_transfer(target, elem);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个用法示例:
std::vector<int> v{1,2,3};
std::set<std::vector<std::deque<int>>, std::greater<>> vv{{{4,5}, {6,7}, {8,9}}, {{10,11,12}, {13,14}, {15}}};
flat_transfer(v, vv);
// prints "1 2 3 10 11 12 13 14 15 4 5 6 7 8 9"
for(const auto& i : v){
std::cout << i << " ";
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
247 次 |
最近记录: |