我有一堆结构std::array
,其中包含不同数量的预先排序的size_t
s。作为一个玩具示例,假设我们有以下三个结构:
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
-way等效的操作;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
以允许将任意数量的此类结构指定为模板参数?