C++ 数组的constexpr初始化以对内容进行排序

C++ 数组的constexpr初始化以对内容进行排序,c++,c++11,template-meta-programming,constexpr,C++,C++11,Template Meta Programming,Constexpr,这是一个谜,而不是一个现实世界的问题,但我已经进入了一个情况,我想能够写一些行为完全一样的东西 template<int N> struct SortMyElements { int data[N]; template<typename... TT> SortMyElements(TT... tt) : data{ tt... } { std::sort(data, data+N); } }; int main(

这是一个谜,而不是一个现实世界的问题,但我已经进入了一个情况,我想能够写一些行为完全一样的东西

template<int N>
struct SortMyElements {
    int data[N];

    template<typename... TT>
    SortMyElements(TT... tt) : data{ tt... }
    {
        std::sort(data, data+N);
    }
};

int main() {
    SortMyElements<5> se(1,4,2,5,3);
    int se_reference[5] = {1,2,3,4,5};
    assert(memcmp(se.data, se_reference, sizeof se.data) == 0);
}
但我如何将其概括为适用于任何
N


请注意,数组元素必须来自参数的实际值,而不是来自模板非类型参数;我的元素来自
constexpr
表达式,尽管这些表达式在编译时进行了计算,但它们牢牢地驻留在“值系统”中,而不是“类型系统”中。(例如,严格按照“类型系统”工作。)

我已经发布了一个有效的“答案”,但是在
N>6
上工作效率太低了。我想把它和
2
或差不多的东西一起使用


(顺便说一句,实际上我真正想做的是将数组中的所有零移动到数组的末尾,并将非零值放在前面,这可能比完全排序更容易;但我认为排序更容易描述。请随意处理“移动零”问题,而不是排序。)

,我得到了效率低下的版本来编译,至少在OSX上是这样的。这是密码

然而,虽然五个元素的排序速度相当快,但在我的笔记本电脑上,六个元素的排序需要0.5秒,七个元素的排序需要7秒。(性能也发生了灾难性的变化,这取决于项目是几乎排序还是反向排序。)我甚至没有尝试计时8。很明显,这并不适合我想用它做的事情。(我认为50个元素是我设计的用例的合理上限,但6个元素太小了。)

#包括
#包括
模板
结构IntHolder{};
//现在让我们做一个从[a到B]的连续整数范围。
模板

struct IntRange(内部结构:内部结构对我来说可能是可行的)。然而,今天早上我解决了我最初的难题,将零拖到数组末尾!我使用了递归分区和合并算法;代码看起来很难看,可能不是在常量表达式中排序的最佳方式(因为需要实例化深度)…但是瞧,合并排序:

template<std::size_t Res, class T, class It, std::size_t Accum,
         class = typename std::enable_if<Res!=Accum, void>::type >
constexpr c_array<T, Res> c_merge(It beg0, It end0, It beg1, It end1,
                                  c_array<T, Accum> const& accum)
{
    return
beg0 == end0  ? c_merge<Res>(beg0  , end0, beg1+1, end1, append(accum, *beg1)) :
beg1 == end1  ? c_merge<Res>(beg0+1, end0, beg1  , end1, append(accum, *beg0)) :
*beg0 < *beg1 ? c_merge<Res>(beg0+1, end0, beg1  , end1, append(accum, *beg0))
              : c_merge<Res>(beg0  , end0, beg1+1, end1, append(accum, *beg1));
}
template<std::size_t Res, class T, class It, class... Dummies>
constexpr c_array<T, Res> c_merge(It beg0, It end0, It beg1, It end1,
                                  c_array<T, Res> const& accum, Dummies...)
{
    return accum;
}

template<class T, std::size_t L, std::size_t R>
constexpr c_array<T, L+R> c_merge(c_array<T, L> const& l,
                                  c_array<T, R> const& r)
{
    return c_merge<L+R>(l.begin(), l.end(), r.begin(), r.end(),
                        c_array<T, 0>{});
}


template<class T>
using rem_ref = typename std::remove_reference<T>::type;

template<std::size_t dist>
struct helper
{
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, dist>
    {
        return c_merge(helper<dist/2>::merge_sort(beg, beg+dist/2),
                       helper<dist-dist/2>::merge_sort(beg+dist/2, end));
    }
};
template<>
struct helper<0>
{
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, 0>
    {
        return {};
    }
};
template<>
struct helper<1>
{   
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, 1>
    {
        return {*beg};
    }
};

template < std::size_t dist, class It >
constexpr auto merge_sort(It beg, It end)
-> c_array<rem_ref<decltype(*beg)>, dist>
{
    return helper<dist>::merge_sort(beg, end);
}
助手类型,可返回数组类型,具有constexpr元素访问权限:

#include <cstddef>
#include <iterator>
#include <type_traits>

template<class T, std::size_t N>
struct c_array
{
    T arr[N];

    constexpr T const& operator[](std::size_t p) const
    { return arr[p]; }

    constexpr T const* begin() const
    { return arr+0; }
    constexpr T const* end() const
    { return arr+N; }
};

template<class T>
struct c_array<T, 0> {};
合并排序:

template<std::size_t Res, class T, class It, std::size_t Accum,
         class = typename std::enable_if<Res!=Accum, void>::type >
constexpr c_array<T, Res> c_merge(It beg0, It end0, It beg1, It end1,
                                  c_array<T, Accum> const& accum)
{
    return
beg0 == end0  ? c_merge<Res>(beg0  , end0, beg1+1, end1, append(accum, *beg1)) :
beg1 == end1  ? c_merge<Res>(beg0+1, end0, beg1  , end1, append(accum, *beg0)) :
*beg0 < *beg1 ? c_merge<Res>(beg0+1, end0, beg1  , end1, append(accum, *beg0))
              : c_merge<Res>(beg0  , end0, beg1+1, end1, append(accum, *beg1));
}
template<std::size_t Res, class T, class It, class... Dummies>
constexpr c_array<T, Res> c_merge(It beg0, It end0, It beg1, It end1,
                                  c_array<T, Res> const& accum, Dummies...)
{
    return accum;
}

template<class T, std::size_t L, std::size_t R>
constexpr c_array<T, L+R> c_merge(c_array<T, L> const& l,
                                  c_array<T, R> const& r)
{
    return c_merge<L+R>(l.begin(), l.end(), r.begin(), r.end(),
                        c_array<T, 0>{});
}


template<class T>
using rem_ref = typename std::remove_reference<T>::type;

template<std::size_t dist>
struct helper
{
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, dist>
    {
        return c_merge(helper<dist/2>::merge_sort(beg, beg+dist/2),
                       helper<dist-dist/2>::merge_sort(beg+dist/2, end));
    }
};
template<>
struct helper<0>
{
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, 0>
    {
        return {};
    }
};
template<>
struct helper<1>
{   
    template < class It >
    static constexpr auto merge_sort(It beg, It end)
    -> c_array<rem_ref<decltype(*beg)>, 1>
    {
        return {*beg};
    }
};

template < std::size_t dist, class It >
constexpr auto merge_sort(It beg, It end)
-> c_array<rem_ref<decltype(*beg)>, dist>
{
    return helper<dist>::merge_sort(beg, end);
}
模板
constexpr c_数组c_merge(它beg0,它end0,它beg1,它end1,
c_阵列常数和累积值)
{
返回
beg0==end0?c_merge(beg0,end0,beg1+1,end1,append(acum,*beg1)):
beg1==end1?c_merge(beg0+1,end0,beg1,end1,append(acum,*beg0)):
*beg0<*beg1?c_合并(beg0+1,end0,beg1,end1,append(累计,*beg0))
:c_merge(beg0,end0,beg1+1,end1,append(acum,*beg1));
}
模板
constexpr c_数组c_merge(它beg0,它end0,它beg1,它end1,
c_阵列常数和累积,假人…)
{
返回累计;
}
模板
constexpr c_数组c_merge(c_数组const&l,
c_阵列常数和r)
{
返回c_merge(l.begin(),l.end(),r.begin(),r.end(),
c_数组{});
}
模板
使用rem_ref=typename std::remove_reference::type;
模板
结构辅助程序
{
模板
静态constexpr自动合并\排序(It beg,It end)
->c_阵列
{
返回c_merge(helper::merge_sort(beg,beg+dist/2),
helper::merge_sort(beg+dist/2,end));
}
};
模板
结构辅助程序
{
模板
静态constexpr自动合并\排序(It beg,It end)
->c_阵列
{
返回{};
}
};
模板
结构辅助程序
{   
模板
静态constexpr自动合并\排序(It beg,It end)
->c_阵列
{
返回{*beg};
}
};
模板
constexpr自动合并\排序(它是beg,它是end)
->c_阵列
{
return helper::merge_sort(beg,end);
}
有关用法的帮助程序示例:

template<class T, std::size_t N>
constexpr std::size_t array_size(T (&arr)[N])  {  return N;  }

template<class T, std::size_t N>
constexpr T* c_begin(T (&arr)[N])  {  return arr;  }

template<class T, std::size_t N>
constexpr T* c_end(T (&arr)[N])  {  return arr+N;  }
constexpr int unsorted[] = {5,7,3,4,1,8,2,9,0,6,10}; // odd number of elements
constexpr auto sorted = merge_sort<array_size(unsorted)>(c_begin(unsorted),
                                                         c_end(unsorted));

#include <iostream>
int main()
{
    std::cout << "unsorted: ";
    for(auto const& e : unsorted) std::cout << e << ", ";
    std::cout << '\n';

    std::cout << "sorted: ";
    for(auto const& e : sorted) std::cout << e << ", ";
    std::cout << '\n';
}
模板
constexpr std::size\u t数组大小(t(&arr)[N]){return N;}
模板
constexpr T*c_begin(T(&arr)[N]){return arr;}
模板
constexpr T*c_end(T(&arr)[N]){return arr+N;}
用法示例:

template<class T, std::size_t N>
constexpr std::size_t array_size(T (&arr)[N])  {  return N;  }

template<class T, std::size_t N>
constexpr T* c_begin(T (&arr)[N])  {  return arr;  }

template<class T, std::size_t N>
constexpr T* c_end(T (&arr)[N])  {  return arr+N;  }
constexpr int unsorted[] = {5,7,3,4,1,8,2,9,0,6,10}; // odd number of elements
constexpr auto sorted = merge_sort<array_size(unsorted)>(c_begin(unsorted),
                                                         c_end(unsorted));

#include <iostream>
int main()
{
    std::cout << "unsorted: ";
    for(auto const& e : unsorted) std::cout << e << ", ";
    std::cout << '\n';

    std::cout << "sorted: ";
    for(auto const& e : sorted) std::cout << e << ", ";
    std::cout << '\n';
}
constexpr int unsorted[]={5,7,3,4,1,8,2,9,0,6,10};//元素奇数
constexpr auto sorted=merge\u sort(c\u begin(unsorted)),
c_端(未排序));
#包括
int main()
{

std::cout我知道这是一个老问题,但由于我们有C++14(很快还有C++17),而且由于C++14 constexpr规则没有那么严格,当然,有几个人会在谷歌上找到你的问题,下面是自C++14以来如何进行快速排序(当然还有其他算法)。 (constexpr阵列的@dyp获得了巨大的荣誉)

#包括
#包括
模板
constexpr无效掉期(T&l、T&r)
{
T tmp=std::move(l);
l=标准::移动(r);
r=std::move(tmp);
}
模板
结构体数组
{
constexpr T&operator[](大小i)
{
返回arr[i];
}
常量表达式常量T和运算符[](大小i)常量
{
返回arr[i];
}
constexpr const T*begin()const
{
返回arr;
}
constexpr const T*end()const
{
返回arr+N;
}
T arr[N];
};
模板
constexpr void sort\u impl(数组和数组,左侧大小,右侧大小)
{
if(左<右)
{
尺寸m=左侧;

对于(size_t i=left+1;i来说,参加聚会有点晚,但是下面的实现更好、更简单

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;
}

int main ( ) {

    constexpr auto sorted = sort ( std::array<int, 8> { 6, 8, 0, 1, 5, 9, 2, 7 } );

    for ( auto i : sorted )
        std::cout << i << ' ';
    std::cout << std::endl;

    return EXIT_SUCCESS;
}
模板
constexpr void comb\u sort\u impl(数组和数组)noexcept{
使用size\u type=typename数组::size\u type;
size_type gap=array_u.size();
布尔交换=假;
while((间隙>大小_类型{1})或交换){
if(间隙>大小_类型{1}){
间隙=静态铸造(间隙/1.247330950103979);
}
交换=假;
对于(size_type i=size_type{0};gap+i<静态_cast(array_u.si
#include <utility>
#include <cstdlib>

template<class T>
constexpr void swap(T& l, T& r)
{
    T tmp = std::move(l);
    l = std::move(r);
    r = std::move(tmp);
}

template <typename T, size_t N>
struct array
{
    constexpr T& operator[](size_t i)
    {
        return arr[i];
    }

    constexpr const T& operator[](size_t i) const
    {
        return arr[i];
    }

    constexpr const T* begin() const
    {
        return arr;
    }
    constexpr const T* end() const
    {
        return arr + N;
    }

    T arr[N];
};

template <typename T, size_t N>
constexpr void sort_impl(array<T, N> &array, size_t left, size_t right)
{
    if (left < right)
    {
        size_t m = left;

        for (size_t i = left + 1; i<right; i++)
            if (array[i]<array[left])
                swap(array[++m], array[i]);

        swap(array[left], array[m]);

        sort_impl(array, left, m);
        sort_impl(array, m + 1, right);
    }
}

template <typename T, size_t N>
constexpr array<T, N> sort(array<T, N> array)
{
    auto sorted = array;
    sort_impl(sorted, 0, N);
    return sorted;
}

constexpr array<int, 11> unsorted{5,7,3,4,1,8,2,9,0,6,10}; // odd number of elements
constexpr auto sorted = sort(unsorted);

#include <iostream>
int main()
{
    std::cout << "unsorted: ";
    for(auto const& e : unsorted) 
      std::cout << e << ", ";
    std::cout << '\n';

    std::cout << "sorted: ";
    for(auto const& e : sorted) 
      std::cout << e << ", ";
    std::cout << '\n';
}
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;
}

int main ( ) {

    constexpr auto sorted = sort ( std::array<int, 8> { 6, 8, 0, 1, 5, 9, 2, 7 } );

    for ( auto i : sorted )
        std::cout << i << ' ';
    std::cout << std::endl;

    return EXIT_SUCCESS;
}