简体   繁体   English

对int [2]数组进行排序无法编译

[英]Sorting an array of int[2] does not compile

I have a data array with 2*N ints, representing pairs, that is for even i=0,2,4,...,2*N (pairs[i], pairs[i+1]) is such a pair. 我有一个具有2 * N个整数的数据数组,表示对,即使i = 0,2,4,...,2 * N(pairs [i],pairs [i + 1])也是如此。 The data is formatted like this because I use Matlab's mex library. 数据的格式是这样的,因为我使用的是Matlab的mex库。 I do: 我做:

int N=5;
int data[10] = {1,2,3,4,5,6,7,8,9,10};
struct Pair { int first; int second; };
Pair * pairs = (Pair *)data;

but the problem would be that there is no way to guarantee that Pair aligns as two sizeof(ints) in order first, second. 但是问题在于,没有办法保证Pair对齐为两个sizeof(ints)顺序为第一,第二。 See: Is the member field order of a class "stable"? 请参阅: 类的成员字段顺序是否“稳定”?

I don't want to process and copy all data into a new array, since it should not be necessary, and I need (as far as I can see) to use 我不想处理所有数据并将其复制到一个新数组中,因为它不是必需的,并且我需要(据我所知)可以使用

typedef int Pair[2];

to be sure that it aligns correctly (no trailing garbage bytes, etc). 确保它正确对齐(没有尾随垃圾字节等)。 if I then want to sort the pairs according to the first element, I could do: 如果然后我想根据第一个元素对对进行排序,则可以执行以下操作:

#include <iostream>
#include <algorithm>

typedef int Pair[2];

int compare(Pair n1, Pair n2) { return n1[0] < n2[0]; }

int main() {
    int N=5;
    int data[10] = {1,2, 7,8, 13,14, 4,5, 10,11};
    Pair *pairs  = (Pair *)((void *)data); 

    std::cout << "unsorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;

    std::sort(data, data+N, compare);

    std::cout << "sorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;

    return 0;
}

see: http://ideone.com/VyBUvc 请参阅: http//ideone.com/VyBUvc

I could summarize the error message as error: array must be initialized with a brace-enclosed initializer , see below for the complete message. 我可以将错误消息概括为错误:必须使用大括号括起来的初始化程序来初始化数组 ,有关完整消息,请参见下文。 It is caused by the std::sort call. 它是由std :: sort调用引起的。

I wrapped the Pair typedef in a union here ( http://ideone.com/TVmEeZ ), and that seems to work. 我将Pair typedef封装在这里的一个联合体中( http://ideone.com/TVmEeZ ),这似乎可行。 Why does c++ (or std::sort) not see int[2] in a similar way as a union? 为什么C ++(或std :: sort)看不到int [2]的方式与并集相似?

Complete compiler output: 完整的编译器输出:

In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
                                from /usr/include/c++/4.8/bits/stl_algobase.h:64,
                                from /usr/include/c++/4.8/bits/char_traits.h:39,
                                from /usr/include/c++/4.8/ios:40,
                                from /usr/include/c++/4.8/ostream:38,
                                from /usr/include/c++/4.8/iostream:39,
                                from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2250:70:   required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5514:55:   required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35:   required from here
/usr/include/c++/4.8/bits/stl_algo.h:2186:11: error: array must be initialized with a brace-enclosed initializer
    __val = _GLIBCXX_MOVE(*__i);
                    ^
In file included from /usr/include/c++/4.8/algorithm:62:0,
                                from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_algo.h:2188:17: error: invalid array assignment
                *__first = _GLIBCXX_MOVE(__val);
                                ^
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&, _Compare) [with _RandomAccessIterator = int (*)[2]; _Tp = int [2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2319:78:   required from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2360:62:   required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44:   required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35:   required from here
/usr/include/c++/4.8/bits/stl_algo.h:2287:35: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
        while (__comp(*__first, __pivot))
                                                                    ^
/usr/include/c++/4.8/bits/stl_algo.h:2290:34: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
        while (__comp(__pivot, *__last))
                                                                    ^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
                                from /usr/include/c++/4.8/bits/stl_algobase.h:64,
                                from /usr/include/c++/4.8/bits/char_traits.h:39,
                                from /usr/include/c++/4.8/ios:40,
                                from /usr/include/c++/4.8/ostream:38,
                                from /usr/include/c++/4.8/iostream:39,
                                from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::make_heap(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1970:47:   required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59:   required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68:   required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44:   required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35:   required from here
/usr/include/c++/4.8/bits/stl_heap.h:446:25: error: array must be initialized with a brace-enclosed initializer
        _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
                                                ^
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::__pop_heap(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1973:50:   required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59:   required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68:   required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44:   required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35:   required from here
/usr/include/c++/4.8/bits/stl_heap.h:339:28: error: array must be initialized with a brace-enclosed initializer
            _ValueType __value = _GLIBCXX_MOVE(*__result);
                                                        ^
In file included from /usr/include/c++/4.8/bits/stl_algo.h:61:0,
                                from /usr/include/c++/4.8/algorithm:62,
                                from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_heap.h:340:17: error: invalid array assignment
            *__result = _GLIBCXX_MOVE(*__first);
                                ^
 std::sort(data, data+N, compare); 

You are sorting data , not pairs . 您正在排序data ,而不是pairs That said, your new approach is still undefined behaviour, and thus not guaranteed to work 1 . 也就是说,您的新方法仍然是不确定的行为,因此不能保证能正常工作1 You are essentially trying to fit a square peg into a round hole. 您实质上是在尝试将方形钉插入圆孔中。 If you want to use std::sort , present valid data – which means copying in your case, or writing a custom iterator which treats an array as a collection of consecutive pairs. 如果要使用std::sort ,请显示有效数据–这意味着要进行复制,或编写一个自定义迭代器将数组视为连续对的集合。


1 That's a humungous understatement. 1轻描淡写。 Do not do this. 不要这样做。

Exchanging your array of two int for a std::pair<int,int> did the trick for me ( live at ideone ): 用两个int数组交换一个std::pair<int,int>帮了我大忙住在ideone ):

#include <iostream>
#include <algorithm>
#include <memory>

typedef std::pair<int,int> Pair;

bool compare(const Pair& i, const Pair& j) { return i.first < j.first; }

int main() {
    const int N=5;
    Pair pairs[N] = {{1,2}, {7,8}, {13,14}, {4,5}, {10,11}};

    std::cout << "unsorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;

    std::sort(pairs, pairs+N, compare);

    std::cout << "sorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;
}

An alternative would be encapsulating the array of two int inside a struct. 另一种选择是将两个int数组封装在一个struct中。 The problem in your code is that std::sort need an array of comparable (you fixed it with your compare function) and copy-or-move-assignable items (arrays are neither) 您的代码中的问题是std::sort需要一个可比较的数组(您使用compare函数对其进行了修复)和可复制或移动的可分配项(数组都不是)

Maybe even better (less changes to your code) would be using std::array : 甚至更好(对代码的更改更少)将使用std::array

#include <iostream>
#include <algorithm>
#include <memory>

typedef std::array<int, 2> Pair;

bool compare(const Pair& i, const Pair& j) { return i[0] < j[0]; }

int main() {
    const int N=5;
    Pair pairs[N] = {1,2, 7,8, 13,14, 4,5, 10,11};

    std::cout << "unsorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;

    std::sort(pairs, pairs+N, compare);

    std::cout << "sorted" << std::endl;
    for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM