gpt4 book ai didi

c++ - 连接 std::vector 容器的可变参数模板函数

转载 作者:太空狗 更新时间:2023-10-29 23:40:04 25 4
gpt4 key购买 nike

在学习模板参数包时,我正在尝试编写一个聪明、简单的函数来有效地将两个或多个 std::vector 容器附加在一起。

下面是两个初步的解决方案。

版本 1 很优雅但有问题,因为它依赖于参数包扩展期间的副作用,并且评估顺序未定义。

版本 2 有效,但依赖于需要两个 case 的辅助函数。呸。

你能不能想出一个更简单的解决方案?(为了效率, vector 数据不应复制超过一次。)

#include <vector>
#include <iostream>

// Append all elements of v2 to the end of v1.
template<typename T>
void append_to_vector(std::vector<T>& v1, const std::vector<T>& v2) {
for (auto& e : v2) v1.push_back(e);
}

// Expand a template parameter pack for side effects.
template<typename... A> void ignore_all(const A&...) { }

// Version 1: Concatenate two or more std::vector<> containers into one.
// Nicely simple, but buggy as the order of evaluation is undefined.
template<typename T, typename... A>
std::vector<T> concat1(std::vector<T> v1, const A&... vr) {
// Function append_to_vector() returns void, so I enclose it in (..., 1).
ignore_all((append_to_vector(v1, vr), 1)...);
// In fact, the evaluation order is right-to-left in gcc and MSVC.
return v1;
}

// Version 2:
// It works but looks ugly.
template<typename T, typename... A>
void concat2_aux(std::vector<T>& v1, const std::vector<T>& v2) {
append_to_vector(v1, v2);
}

template<typename T, typename... A>
void concat2_aux(std::vector<T>& v1, const std::vector<T>& v2, const A&... vr) {
append_to_vector(v1, v2);
concat2_aux(v1, vr...);
}

template<typename T, typename... A>
std::vector<T> concat2(std::vector<T> v1, const A&... vr) {
concat2_aux(v1, vr...);
return v1;
}

int main() {
const std::vector<int> v1 { 1, 2, 3 };
const std::vector<int> v2 { 4 };
const std::vector<int> v3 { 5, 6 };
for (int i : concat1(v1, v2, v3)) std::cerr << " " << i;
std::cerr << "\n"; // gcc output is: 1 2 3 5 6 4
for (int i : concat2(v1, v2, v3)) std::cerr << " " << i;
std::cerr << "\n"; // gcc output is: 1 2 3 4 5 6
}

最佳答案

辅助类型:我不喜欢为它使用 int

struct do_in_order { template<class T>do_in_order(T&&){}};

加起来尺寸:'

template<class V>
std::size_t sum_size( std::size_t& s, V&& v ) {return s+= v.size(); }

连续。返回类型被忽略:

template<class V>
do_in_order concat_helper( V& lhs, V const& rhs ) { lhs.insert( lhs.end(), rhs.begin(), rhs.end() ); return {}; }

微优化,并允许您连接仅移动类型的 vector :

template<class V>
do_in_order concat_helper( V& lhs, V && rhs ) { lhs.insert( lhs.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()) ); return{}; }

实际功能。以上内容应该在 details 命名空间中:

template< typename T, typename A, typename... Vs >
std::vector<T,A> concat( std::vector<T,A> lhs, Vs&&...vs ){
std::size s=lhs.size();
do_in_order _0[]={ sum_size(s,vs)..., 0 };
lhs.reserve(s);
do_in_order _1[]={ concat_helper( lhs, std::forward<Vs>(vs) )..., 0 };
return std::move(lhs); // rvo blocked
}

对任何打字错误表示歉意。

关于c++ - 连接 std::vector 容器的可变参数模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23439221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com