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;
};
是否可以让编译器创建组合?
是的,我希望创建数组。
更多信息:
createP2E的参数(枚举的位置)是一个枚举。
创建的数组P2E应该包含按排序顺序的枚举。
事后编辑:
我可能不清楚我的问题:
我想通过使用constexpr而不是boost::mpl::set或boost::mp11::list <>的元编程来合并两个提供的集合。结果集应该再次可以用于合并。
最佳答案
我想可以做到的。正如您已经说过的,这里的核心问题是将一个数组追加到另一个数组然后对其进行排序。这是基于c++ 17 解决此问题的方法。不幸的是,它使用std::arrays
而不是c数组。
我只是简单地将这个answer和这个code结合在一起就可以得到(满分功)#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;
}
这是live demo。
备注:如果Combine将始终只合并两个存储一个元素的createP2E,则可能有更简单的解决方案。但是,这种通用方法允许您组合两个combine
对象。但是,您需要添加一些功能,以从组合数组中删除重复项以具有正确的枚举。
更新这是一个解决方案,它返回已排序的数组,其中删除了重复项。这不是很好,但是可以完成工作(live demo):#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;
}
关于c++ - C++中可能进行以下编译时编程任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61787089/