如何实现 constexpr N 路set_union(重复数据删除合并)
How can I implement a constexpr N-way set_union (deduplicated merge)
我有一堆结构,保存不同数量的size_t
的预排序std::array
。举个玩具示例,假设我们有以下三个结构:
struct F_A { static constexpr std::array<size_t, 4> bounds = { 0, 100, 200, 300 }; };
struct F_B { static constexpr std::array<size_t, 5> bounds = { 0, 125, 250, 300, 500 }; };
struct F_C { static constexpr std::array<size_t, 4> bounds = { 100, 250, 300, 301 }; };
目标是在编译时执行相当于N
方式std::set_union
;例如,给定上述结构,我希望能够编写
constexpr auto bounds = merge_bounds<F_A,F_B,F_C>();
并以bounds
作为包含值的constexpr std::array<size_t, 8>
0, 100, 125, 200, 250, 300, 301, 500
.
从一对结构合并bounds
数组非常容易;但是,对于如何最好地概括它以使用可变参数模板和参数包,我有点不知所措。为了使具有对的版本正常工作,我首先"模拟"合并以确定合并后的数组在实际进行合并之前需要多长时间,但是这种方法在与参数包组合时变得非常棘手。(我怀疑即使是我的成对代码也远不如我更好地处理一些相关语言功能时那么优雅......
这是一个 MWE 演示了我的成对功能代码:
#include <cstdlib>
#include <iostream>
#include <array>
struct F_A { static constexpr std::array<size_t, 4> bounds = { 0, 100, 200, 300 }; };
struct F_B { static constexpr std::array<size_t, 5> bounds = { 0, 125, 250, 300, 500 }; };
struct F_C { static constexpr std::array<size_t, 4> bounds = { 100, 250, 300, 301 }; };
template <typename F0, typename F1>
inline static constexpr auto merged_size()
{
constexpr auto bnd0 = F0::bounds;
constexpr auto bnd1 = F1::bounds;
size_t i = 0, i0 = 0, i1 = 0;
while (i0 < bnd0.size() && i1 < bnd1.size())
{
if (bnd0[i0] < bnd1[i1]) { i++; i0++; }
else if (bnd0[i0] > bnd1[i1]) { i++; i1++; }
else { i++; i0++; i1++; }
}
while (i0 < bnd0.size()) { i++; i0++; }
while (i1 < bnd1.size()) { i++; i1++; }
return i;
}
template <typename F0, typename F1, size_t N = merged_size<F0,F1>()>
inline static constexpr auto merge_bounds()
{
std::array<size_t, N> merged = { 0 };
constexpr auto bnd0 = F0::bounds;
constexpr auto bnd1 = F1::bounds;
size_t i = 0, i0 = 0, i1 = 0;
while (i0 < bnd0.size() && i1 < bnd1.size())
{
if (bnd0[i0] < bnd1[i1]) { merged[i++] = bnd0[i0++]; }
else if (bnd0[i0] > bnd1[i1]) { merged[i++] = bnd1[i1++]; }
else { merged[i++] = bnd0[i0++]; i1++; }
}
while (i0 < bnd0.size()) { merged[i++] = bnd0[i0++]; }
while (i1 < bnd1.size()) { merged[i++] = bnd1[i1++]; }
return std::move(merged);
}
int main(int argc, char * argv[])
{
std::cout << merged_size<F_A,F_B>() << "," << merged_size<F_B,F_C>() << "," << merged_size<F_A,F_C>() << std::endl;
for (auto i : merge_bounds<F_A,F_B>()) std::cout << i << " ";
std::cout <<"n";
for (auto i : merge_bounds<F_B,F_C>()) std::cout << i << " ";
std::cout <<"n";
for (auto i : merge_bounds<F_A,F_C>()) std::cout << i << " ";
std::cout <<"n";
return 0;
}
如何泛化merge_bounds
以允许将任意数量的此类结构指定为模板参数?
拥抱价值观。
template<class T, std::size_t N>
struct partial_array:std::array<T,N>{
std::size_t partial=N;
constexpr std::size_t size()const{return partial;}
constexpr T* end()const{return this->begin()+partial;}
//etc
};
template<class T, std::size_t N, std::size_t M, std::size_t...Ms>
constexpr partial_array<T,N+M> merge(partial_array<T,N>,partial_array<T,M>);
template<class T, std::size_t N, std::size_t M>
constexpr partial_array<T,N+(M+Ms...)> merge(partial_array<T,N> a,partial_array<T,M> b, partial_array<T,Ms>... cs){
return merge( a, merge(b,cs...) );
}
现在你只需获取数组,将它们转换为部分数组,合并它们。 结果是一个具有 constexpr 大小的 constexpr 部分数组。
将该 constexpr 大小转换为数组边界,然后复制数据。
template <class...Ts>
constexpr auto merge_bounds() {
constexpr auto merged = merge(partial_array{Ts::bounds}...);// do some magic to make this compile; maybe deduction guilds and a ctor?
std::array<T,merged.size()> retval = merged; // add an operator std::array<T,X> to partial array
return retval;
}
代码可能充满了错别字,但我希望你明白这个想法。
相关文章:
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 如何以"union-like"方式更改C++向量的数据类型
- c语言中的Union每次存储一个数据