Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带选择算法的编译时递归排序 P>可以使用C++选择算法< < /P>编写C++中的编译时递归排序函数吗?_C++_C++11 - Fatal编程技术网

带选择算法的编译时递归排序 P>可以使用C++选择算法< < /P>编写C++中的编译时递归排序函数吗?

带选择算法的编译时递归排序 P>可以使用C++选择算法< < /P>编写C++中的编译时递归排序函数吗?,c++,c++11,C++,C++11,我想按升序将数组x从元素istart排序到元素iend。数组x具有N元素。输入数组x中的数据仅在运行时已知,因此只能在运行时对数据进行排序。但是,我想在编译时生成C++代码,即所有的递归函数调用 SoToSyCase](< /代码>)。此外,我想在CUDA设备函数中使用此代码。由于CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持constexpr关键字,也不支持Boost和STL 我提出了以下代码,用于按升序排序 // sort in ascendin

我想按升序将数组
x
从元素
istart
排序到元素
iend
。数组
x
具有
N
元素。输入数组
x
中的数据仅在运行时已知,因此只能在运行时对数据进行排序。但是,我想在编译时生成C++代码,即所有的递归函数调用<代码> SoToSyCase](< /代码>)。此外,我想在CUDA设备函数中使用此代码。由于CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持
constexpr
关键字,也不支持Boost和STL


我提出了以下代码,用于按升序排序

// sort in ascending order.
template< int istart, int N, int iend, int iend_min_istart >
inline void sort_asc
(
    float *x
)
{
    int   min_idx = istart;
    float min_val = x[ min_idx ];
    #pragma unroll
    for( int i=istart+1; i<N; i++ ){
        if( x[ i ] < min_val ){
            min_idx = i;
            min_val = x[ i ];
        }
    }
    swap( x[ istart ], x[ min_idx ] );
    sort_asc< istart+1, N, iend, iend-(istart+1) >( x );
}   
交换功能定义为:

void d_swap
( 
    float &a, 
    float &b 
)
{
    float c = a;
    a = b;
    b = c;
}
然后我将调用排序函数,如下所示:

void main( int argc, char *argv[] )
{
    float x[] = { 3, 4, 9, 2, 7 };   // 5 element array.
    sort_asc< 0, 5, 2, 2-0 >( x );   // sort from the 1st till the 3th element.
    float x_median = cost[ 2 ];      // the 3th element is the median
}
void main(int-argc,char*argv[])
{
浮点x[]={3,4,9,2,7};//5元素数组。
sort_asc<0,5,2,2-0>(x);//从第一个元素到第三个元素进行排序。
浮动x_中位数=成本[2];//第三个元素是中位数
}

但是,由于C++不支持函数的部分模板特化,所以此代码不编译。此外,我不知道如何在C++元编程中编写这个。有什么方法可以让这段代码工作吗?

这次使用选择排序。(.) 没有任何保证,但通过了一个简单的测试:

// generate a sequence of integers as non-type template arguments
// (a basic meta-programming tool)
template<int... Is> struct seq {};
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {};


// an array type that can be returned from a function
// and has `constexpr` accessors (as opposed to C++11's `std::array`)
template<class T, int N>
struct c_array
{
    T m[N];

    constexpr T const& operator[](int p) const
    {  return m[p];  }

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


// return the index of the smallest element
template<class T, int Size>
constexpr int c_min_index(c_array<T, Size> const& arr, int offset, int cur)
{
    return Size == offset ? cur :
           c_min_index(arr, offset+1, arr[cur] < arr[offset] ? cur : offset);
}
由于
constexpr
函数限制,我们无法修改参数,因此我们需要返回整个数组的一个副本来交换两个元素

函数期望
是…
是一个整数序列
0,1,2。。大小-1,由
gen_seq{}
生成(在其基类中)。这些整数用于访问数组的元素
arr
。一些表达式,如
arr[Is]…
将生成
arr[0]、arr[1]、arr[2]。。arr[Size-1]
。这里,我们通过对当前整数应用一个条件来交换索引:
a[0==index0?index1:0==index1?index0:0],…

// the selection sort algorithm
template<class T, int Size>
constexpr c_array<T, Size> c_sel_sort(c_array<T, Size> const& arr, int cur = 0)
{
    return cur == Size ? arr :
           c_sel_sort( c_swap(arr, cur, c_min_index(arr, cur, cur),
                              gen_seq<Size>{}),
                       cur+1 );
}

我想出了下面的元代码,它是有效的

template < class T >
__forceinline void swap
( 
    T &a, 
    T &b 
)
{
    T c = a;
    a = b;
    b = c;
}

template< int istart, int N, int iend, int iend_min_istart >
class SORT
{
    public:
        static __forceinline void sort( float *x, int *idx )
        {
            // sort code.
            int   min_idx = istart;
            float min_val = x[ min_idx ];
            for( int i=istart+1; i<N; i++ ){
                if( x[ i ] < min_val ){
                    min_idx = i;
                    min_val = x[ i ];
                }
            }
            swap(   x[ istart ],   x[ min_idx ] );
            swap( idx[ istart ], idx[ min_idx ] );
            SORT<istart+1, N, iend, iend-(istart+1)>::sort( x, idx );
        }
};

template< int istart, int N, int iend >
class SORT<istart,N,iend,-1>
{
    public:
        static __forceinline void sort( float *x, int *idx )
        {

        }
};

void main( int argc, char *argv[] )
{
    float arr[] = {1,4,2,7,5};
    int   idx[] = {0,1,2,3,4};
    SORT<0,5,3,2-0>::sort( arr, idx );
}
模板
__强制无效交换
( 
T&a,
T&b酒店
)
{
tc=a;
a=b;
b=c;
}
模板
类排序
{
公众:
静态强制内联无效排序(float*x,int*idx)
{
//排序代码。
int min_idx=istart;
浮动最小值=x[min_idx];
对于(int i=istart+1;i
类排序
{
公众:
静态强制内联无效排序(float*x,int*idx)
{
}
};
void main(int argc,char*argv[])
{
浮点arr[]={1,4,2,7,5};
int idx[]={0,1,2,3,4};
SORT::SORT(arr,idx);
}

Related:通常可以使用重载代替部分专门化。使用
std::integral_常量
,让编译器推断
N
;另一个重载使用固定的
N
,因此在重载解析方面更专业,更受欢迎。Boost解决方案(看起来像一个快速排序)此外,为了使我的问题更具体:输入数组<代码> x>代码>的数据只在运行时才知道,因此数据只能在运行时排序。但是,我想生成C++代码,即所有递归函数调用排序::此外,我想在CUDA设备函数中使用这个代码。因为CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持<代码> CONTXPRP<代码>关键字,既不支持Boost也不支持STL。我认为您应该将这部分添加到您的问题中。(作为编辑,而不仅仅是评论),因为这是非常重要的。我很惊讶
c_swap
可以如此轻松地实现。我曾预料到会有更多的麻烦。有趣的是,这是用铿锵编译的,而不是g++。@remyabel是的,我在实现合并排序时就已经遇到了这个问题。我认为可以通过传递
c_数组来避免这个问题e> 它本身不是指针。@remyabel Voilá,到处使用
c_数组
,现在g++4.8.1也很高兴。虽然我不太清楚这是一个铿锵的扩展还是g++错误(倾向于认为是前者)我想它现在也变得更简单了,但不幸的是,它与 CyLaule >非常不同。非常感谢你的详细代码和解释。我很感激。我将深入研究C++的元编程,了解这个代码是如何在引擎盖下工作的。但是如果编译器解决了这个问题,这只是编译时间。作为一种优化,这意味着您得不到可以在需要常量表达式的上下文中使用的结果。@DyP,我有以下情况:输入数组
x
中的数据仅在运行时已知,其长度
N
istart
iend
在编译时已知。(main函数中的代码< >代码> AR/<代码>只是作为示例,但是它的内容在我的应用程序中不在编译时知道),因此,我必须在运行时对数据进行排序。但是,我想生成C++代码,即递归函数调用到<代码>排序::
,用于在编译时将长度为
N
的数组从元素
istart
排序到元素
iend
。编译器会为我这样做吗?这取决于编译器是否实际内联。
\u forceinline
,尽管它的名称不同,但并不强制内联(至少对于MSVC++)。但现在您的算法对我来说更有意义;)我建议不要使用我的(
constexpr
)进行运行时排序。也许我稍后会添加另一个答案,演示我在对您的问题的评论中提到的重载技巧。它
// the selection sort algorithm
template<class T, int Size>
constexpr c_array<T, Size> c_sel_sort(c_array<T, Size> const& arr, int cur = 0)
{
    return cur == Size ? arr :
           c_sel_sort( c_swap(arr, cur, c_min_index(arr, cur, cur),
                              gen_seq<Size>{}),
                       cur+1 );
}
#include <iostream>
#include <iterator>

int main()
{
    // homework: write a wrapper so that C-style arrays can be passed
    //           to an overload of `c_sel_sort` ;)
    constexpr c_array<float,10> f = {{4, 7, 9, 0, 6, 2, 3, 8, 1, 5}};
    constexpr auto sorted = c_sel_sort(f);
    for(auto const& e : sorted) std::cout << e << ", ";
}
template < class T >
__forceinline void swap
( 
    T &a, 
    T &b 
)
{
    T c = a;
    a = b;
    b = c;
}

template< int istart, int N, int iend, int iend_min_istart >
class SORT
{
    public:
        static __forceinline void sort( float *x, int *idx )
        {
            // sort code.
            int   min_idx = istart;
            float min_val = x[ min_idx ];
            for( int i=istart+1; i<N; i++ ){
                if( x[ i ] < min_val ){
                    min_idx = i;
                    min_val = x[ i ];
                }
            }
            swap(   x[ istart ],   x[ min_idx ] );
            swap( idx[ istart ], idx[ min_idx ] );
            SORT<istart+1, N, iend, iend-(istart+1)>::sort( x, idx );
        }
};

template< int istart, int N, int iend >
class SORT<istart,N,iend,-1>
{
    public:
        static __forceinline void sort( float *x, int *idx )
        {

        }
};

void main( int argc, char *argv[] )
{
    float arr[] = {1,4,2,7,5};
    int   idx[] = {0,1,2,3,4};
    SORT<0,5,3,2-0>::sort( arr, idx );
}