I guess it can be done. As you already have stated, the core problem here is append one array to another and then sort it. Here is a solution to this problem based on c++17. Unfortunately, it uses std::arrays
and not c-array as you do.
I simply combined this answer and this code to get (full credit to them):
#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;
}
Here's a live demo.
Remark: If combine will always only combine two createP2E which store one element, there might be much simpler solutions. However, this general approach allows you, to combine a two combine
objects. However, you need to add some functionality which removes duplicates from the combined array to have a proper enumeration.
UPDATE Here is a solution with returns an sorted array with the duplicates removed. It is not nice, but it does the job (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;
}