以下编译时编程任务在C++中是可能的

is the following compile time programming task possible in C++

本文关键字:C++ 编译 编程 任务      更新时间:2023-10-16
template<std::size_t ENUM>
struct createP2E
{    static constexpr std::size_t SIZE = 1;
static constexpr std::size_t P2E[SIZE] = {ENUM};
};
template<typename A, typename B>
struct combine;
template<>
struct combine<createP2E<2>, createP2E<3> >
{       static constexpr std::size_t SIZE = 2;
static constexpr std::size_t P2E[2] = {2, 3};
typedef combine type;
};
template<typename A>
struct combine<A, A>
{       typedef A type;
};

是否可以让编译器创建组合? 是的,我希望创建数组。 更多信息: 创建 P2E(位置到枚举(的参数是一个枚举。 创建的数组 P2E 应按排序顺序包含枚举。

事后编辑:

我的问题可能不清楚:

我希望通过使用 constexpr 而不是 boost::mpl::set 或 boost::mp11::list<> 通过元编程合并提供的两个集合。结果集应该可以再次用于合并。

我想这是可以做到的。正如您已经说过的,这里的核心问题是将一个数组附加到另一个数组,然后对其进行排序。下面是基于 c++17 的此问题的解决方案。不幸的是,它像您那样使用std::arrays而不是 c 数组。

我只是简单地结合了这个答案和这个代码来得到(完全归功于他们(:

#include <iostream>
#include <array>
namespace detail
{
template<std::size_t ... Size>
struct num_tuple
{
};
template<std::size_t Prepend, typename T>
struct appender {};
template<std::size_t Prepend, std::size_t ... Sizes>
struct appender<Prepend, num_tuple<Sizes...>>
{
using type = num_tuple<Prepend, Sizes...>;
};
template<std::size_t Size, std::size_t Counter = 0>
struct counter_tuple
{
using type = typename appender<Counter, typename counter_tuple<Size, Counter+1>::type>::type;
};

template<std::size_t Size>
struct counter_tuple<Size, Size>
{
using type = num_tuple<>;
};
}

template<typename T, std::size_t LL, std::size_t RL, std::size_t ... LLs, std::size_t ... RLs>
constexpr std::array<T, LL+RL> join(const std::array<T, LL> rhs, const std::array<T, RL> lhs, detail::num_tuple<LLs...>, detail::num_tuple<RLs...>)
{
return {rhs[LLs]..., lhs[RLs]... };
};

template<typename T, std::size_t LL, std::size_t RL>
constexpr std::array<T, LL+RL> join(std::array<T, LL> rhs, std::array<T, RL> lhs)
{
//using l_t = typename detail::counter_tuple<LL>::type;
return join(rhs, lhs, typename detail::counter_tuple<LL>::type(), typename detail::counter_tuple<RL>::type());
}

template<typename Array>
constexpr void comb_sort_impl ( Array & array_ ) noexcept {
using size_type = typename Array::size_type;
size_type gap = array_.size ( );
bool swapped = false;
while ( ( gap > size_type { 1 } ) or swapped ) {
if ( gap > size_type { 1 } ) {
gap = static_cast<size_type> ( gap / 1.247330950103979 );
}
swapped = false;
for ( size_type i = size_type { 0 }; gap + i < static_cast<size_type> ( array_.size ( ) ); ++i ) {
if ( array_ [ i ] > array_ [ i + gap ] ) {
auto swap = array_ [ i ];
array_ [ i ] = array_ [ i + gap ];
array_ [ i + gap ] = swap;
swapped = true;
}
}
}
}
template<typename Array>
constexpr Array sort ( Array array_ ) noexcept {
auto sorted = array_;
comb_sort_impl ( sorted );
return sorted;
}

struct
arr1
{
static constexpr auto values = std::array<int, 9> { 6, 8, 0, 1, 1, 22, 9, 2, 7 };
};
struct
arr2
{
static constexpr auto values = std::array<int,3>{0,12,5};
};
struct
sorted 
{
static constexpr auto values 
= sort ( join(arr1::values,arr2::values) );
};
int main ( ) {
for ( auto i : sorted::values )
std::cout << i << ' ';
std::cout << std::endl;
return EXIT_SUCCESS;
}

这是一个现场演示。

备注:如果组合总是只组合两个存储一个元素的createP2E,则可能会有更简单的解决方案。但是,这种常规方法允许您组合两个combine对象。但是,您需要添加一些功能,从组合数组中删除重复项以进行适当的枚举。

更新这是一个解决方案,返回一个删除重复项的排序数组。这并不好,但它可以完成工作(现场演示(:

#include <iostream>
#include <array>
namespace detail
{
template<std::size_t ... Size>
struct num_tuple
{
};
template<std::size_t Prepend, typename T>
struct appender {};
template<std::size_t Prepend, std::size_t ... Sizes>
struct appender<Prepend, num_tuple<Sizes...>>
{
using type = num_tuple<Prepend, Sizes...>;
};
template<std::size_t Size, std::size_t Counter = 0>
struct counter_tuple
{
using type = typename appender<Counter, typename counter_tuple<Size, Counter+1>::type>::type;
};

template<std::size_t Size>
struct counter_tuple<Size, Size>
{
using type = num_tuple<>;
};
}

template<typename T, std::size_t LL, std::size_t RL, std::size_t ... LLs, std::size_t ... RLs>
constexpr std::array<T, LL+RL> join(const std::array<T, LL> rhs, const std::array<T, RL> lhs, detail::num_tuple<LLs...>, detail::num_tuple<RLs...>)
{
return {rhs[LLs]..., lhs[RLs]... };
};

template<typename T, std::size_t LL, std::size_t RL>
constexpr std::array<T, LL+RL> join(std::array<T, LL> rhs, std::array<T, RL> lhs)
{
//using l_t = typename detail::counter_tuple<LL>::type;
return join(rhs, lhs, typename detail::counter_tuple<LL>::type(), typename detail::counter_tuple<RL>::type());
}

template<typename Array>
constexpr void comb_sort_impl ( Array & array_ ) noexcept {
using size_type = typename Array::size_type;
size_type gap = array_.size ( );
bool swapped = false;
while ( ( gap > size_type { 1 } ) or swapped ) {
if ( gap > size_type { 1 } ) {
gap = static_cast<size_type> ( gap / 1.247330950103979 );
}
swapped = false;
for ( size_type i = size_type { 0 }; gap + i < static_cast<size_type> ( array_.size ( ) ); ++i ) {
if ( array_ [ i ] > array_ [ i + gap ] ) {
auto swap = array_ [ i ];
array_ [ i ] = array_ [ i + gap ];
array_ [ i + gap ] = swap;
swapped = true;
}
}
}
}



template<typename Array>
constexpr Array sort ( Array array_ ) noexcept {
auto sorted = array_;
comb_sort_impl ( sorted );
return sorted;
}

struct
arr1
{
static constexpr auto values = std::array<int, 9> { 6, 8, 0, 1, 1, 22, 9, 2, 7 };
};
struct
arr2
{
static constexpr auto values = std::array<int,3>{0,12,5};
};
struct
sorted 
{
static constexpr auto values 
= sort ( join(arr1::values,arr2::values) );
};
template <typename T, std::size_t N>
constexpr auto size_without_duplicates (const std::array<T,N> &array_)
{
std::array<T,N> ret = {};
std::size_t count = 1; 
ret[0] = array_[0];
for (unsigned int i = 1; i < N; ++i)
if (array_[i-1] != array_[i])
++count;
return count;
}

template <class T>
constexpr auto remove_duplicates ()
{
std::array<int,size_without_duplicates(T::values)> ret = {};
unsigned int count = 0; 
ret[0] = T::values[0];
for (unsigned int i = 1; i < T::values.size(); ++i)
if (T::values[i-1] != T::values[i])
{
ret[++count] = T::values[i];
}
return ret;
}

struct myset
{
static constexpr auto values = remove_duplicates<sorted>();
};
int main ( ) {

for ( auto i : sorted::values )
std::cout << i << ' ';
std::cout << std::endl;
for ( auto i : myset::values )
std::cout << i << ' ';
std::cout << std::endl;
return EXIT_SUCCESS;
}