STL提供的工具只能用于两个集合,而不能用于N个集合吗?
不是。但是您可以很容易地创建一个,只需提供类似于递归可变模板的内容即可。
if constexpr
部分需要C++17支持。然而,有许多示例可以在C++17之前完成。此外,由于递归调用,参数必须相反地传递,以获得您想要的行为。
(查看在线演示)
#include <vector>
#include <algorithm>
#include <iterator>
template<typename Container, typename... Rest>
Container NSetIntersections(
const Container& container1, const Container& container2, Rest&&... rest) noexcept
{
if constexpr (sizeof...(Rest) == 0)
{
Container result;
std::set_intersection(container1.begin(), container1.end(),
container2.begin(), container2.end(), std::back_inserter(result));
return result;
}
else
{
Container result;
std::set_intersection(container1.begin(), container1.end(),
container2.begin(), container2.end(), std::back_inserter(result));
return NSetIntersections(result, std::forward<Rest>(rest)...);
}
}
int main()
{
std::vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
std::vector<int> v2 = { 2, 3, 4, 7, 8, 9 };
std::vector<int> v3 = { 3, 4, 7, 200 };
std::vector<int> v4 = { 4, 100, 200, 300 };
std::vector<int> v5 = { 4, 100, 200 };
const auto res1 = NSetIntersections(v2, v1);
const auto res2 = NSetIntersections(v3, v2, v1);
const auto res3 = NSetIntersections(v4, v3, v2, v1);
const auto res4 = NSetIntersections(v5, v4, v3, v2, v1);
return 0;
}
为了以自然的方式将参数传递给
NSetIntersections
函数,我建议遵循辅助函数的方式。此外,它还可以处理将单个参数(如果错误地)传递给
NSetIntersections
的情况,并且与
c++11兼容。
(查看在线演示)
#include <vector>
#include <algorithm>
#include <iterator>
namespace helper {
template<typename Container>
Container NSetIntersections(const Container& container1) noexcept {
return container1;
}
template<typename Container>
Container NSetIntersections(const Container& container1, const Container& container2) noexcept
{
Container result;
std::set_intersection(container1.begin(), container1.end(),
container2.begin(), container2.end(), std::back_inserter(result));
return result;
}
template<typename Container, typename... Rest>
Container NSetIntersections(
const Container& container1, const Container& container2, Rest&&... rest) noexcept
{
return helper::NSetIntersections(
helper::NSetIntersections(container1, container2), std::forward<Rest>(rest)...);
}
}
template<typename... Containers>
auto NSetIntersections(Containers&&... rest) noexcept
-> decltype(helper::NSetIntersections(std::forward<Containers>(rest)...))
{
return helper::NSetIntersections(std::forward<Containers>(rest)...);
}
现在,您可以像这样使用参数调用函数:
std::vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
std::vector<int> v2 = { 2, 3, 4, 7, 8, 9 };
std::vector<int> v3 = { 3, 4, 7, 200 };
std::vector<int> v4 = { 4, 100, 200, 300 };
std::vector<int> v5 = { 4, 100, 200 };
const auto res1 = NSetIntersections(v1);
const auto res2 = NSetIntersections(v1, v2);
const auto res3 = NSetIntersections(v1, v2, v3);
const auto res4 = NSetIntersections(v1, v2, v3, v4);
const auto res5 = NSetIntersections(v1, v2, v3, v4, v5);
顺便提一下:在 quick-bench.com 上进行的基准测试显示(对于 5 个已排序容器),如果我们进行 N 次 std::set_intersection
,性能几乎相同。
(在线快速测试)
std::set_intersection
两次:result = (v1 * v2) * v3
。 - pptaszni