Я хотел бы использовать в коде Cython C ++ std :: priority_queue, где каждый элемент должен быть структурой или классом, но я не знаю, как определить компаратор.
Если я рассматриваю priority_queue, элементы которого являются стандартными типами, все выглядит нормально, как в следующем примере:
simple.pyx
# distutils: language = c++
cimport cython
from libcpp.queue cimport priority_queue
def testIntPriorityQueue():
cdef priority_queue[int] q
q.push(5)
q.push(15)
q.push(7)
print('q.top (after pushing 5, 15, 7) = ',q.top())
q.pop()
print('q.top (after popping one item) = ',q.top())`
main.py
import simple
def main():
simple.testIntPriorityQueue()
main()
Когда я выполняю этот код, приоритет_, после правильного нажатия 5, 15 и 7, оказывается сверху наибольшим (15) (как это возвращает q.top) и после выталкивания одного элемента q.top возвращает 7, которое стало наибольшим после удаления 15.
Теперь я хотел бы иметь подобное поведение, но с помещенными в очередь элементами, которые не являются объектами стандартного типа но что-то более сложное.
Я пытался определить такую структуру с помощью следующих вещей:
simple.pxd
cimport cython
ctypedef struct myType:
int key
float a
float b
simple.pyx
# distutils: language = c++
cimport cython
from libc.stdlib cimport malloc, free
from libcpp.queue cimport priority_queue
from libcpp.vector cimport vector
def testPriorityQueue():
cdef myType * item
cdef priority_queue[myType*] q
item = <myType *> malloc(sizeof(myType))
item.key = 20
item.a = 3.
item.b = 4.
q.push(item)
item = <myType *> malloc(sizeof(myType))
item.key = 10
item.a = 1.
item.b = 2.
q.push(item)
item = q.top()
print('q.top',item.key,item.a,item.b)
Теперь не сообщается об ошибке ни от компилятора, ни во время выполнения, но, конечно, порядок в priority_queue не может быть определен, и из выводов, которые я получаю, что элемент на вершина - это последнее нажатие.
* 103 2 * В C ++, чтобы сделать priority_queue для сортировки помещенных элементов в такой ситуации, метод сравнения должен быть предоставлен в качестве аргумента для создания экземпляра очереди, но это, как я обнаружил, должно быть сделано через перегрузку оператора less как в этом примере C ++:
struct ToastCompare
{
bool operator()(const Toast &t1, const Toast &t2) const
{
int t1value = t1.bread * 1000 + t1.butter;
int t2value = t2.bread * 1000 + t2.butter;
return t1value < t2value;
}
};
Я попытался определить аналогичную функцию в cython, добавив следующие строки в файл pyx:
simple.pyx
cdef extern from *:
"""
struct itemCompare{
bool operator() (self, myType *t1, myType *t2) const
{
return t1.key < t2.key;
}
};
"""
ctypedef struct itemCompare
cdef priority_queue[myType*,vector[myType*],itemCompare] q
Но во время компиляции я получаю "шаблонный тип priority_queue получает 1 аргумент, получил ошибку 3" .
Возможно ли в Cython использовать контейнер C ++ priority_queue с объекты пользовательских классов?
Пытаясь следовать предложению @ead, я попытался изменить код следующим образом:
simple.pyx
cdef extern from *:
"""
bool operator<(const myType t1, const myType t2)
{ return t1.key < t2.key;}
"""
def testPriorityQueue():
cdef priority_queue[myType*] q
, оставив в simple. pxd
cimport cython
from libcpp cimport bool
ctypedef struct myType:
int key
float a
float b
, но он не может скомпилировать, давая:
simple. cpp: 694: 26: error: myType не называет оператор типа bool <(const myType t1, const myType t2) </p>
Итак, я попытался переместить определение структуры в C -бразорном коде и удалить его из simple.pxd
simple.pyx
def extern from *:
"""
typedef struct myType{
int key;
float a;
float b;
} myType;
bool operator<(const myType t1, const myType t2)
{return t1.key < t2.key;}
"""
ctypedef struct myType
def testPriorityQueue():
cdef myType * item
cdef priority_queue[myType*] q
item = <myType *> malloc(sizeof(myType))
и теперь ошибка компиляции:
Невозможно принять размер неполного типа 'myType'
Если я оставлю определение структуры также в файле pxd, но удаляю ctypedef struct myType из pyx, ошибка компиляции не возникает, но очередь с приоритетами не сортирует элементы, как будто перегрузка не была выполнена.
Где моя ошибка?