Я хотел бы использовать в коде cython C++ std::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())
< EM> main.py
import simple
def main():
simple.testIntPriorityQueue()
main()
Когда я выполняю этот код, priority_queue после правильного нажатия 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 не может быть определен, и из отпечатков я получаю, что элемент сверху является последним.
В C++, чтобы сделать priority_queue для сортировки отправленных элементов в такой ситуации, метод сравнения должен быть предоставлен в качестве аргумента для создания очереди, но это, как я нашел, должно быть сделано через перегрузку оператора less, как в этот пример С++:
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 использовать контейнер 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: ошибка: «myType» не называет оператор типа bool <(const myType t1, const myType t2)
Поэтому я попытался переместить определение структуры в код C-verbatim и удалить его из 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, ошибки компиляции не возникнет, но очередь приоритетов не сортирует элементы, как если бы не было перегрузки.
Где моя ошибка?
1 ответ
Ответом на мой вопрос было использование следующего файла pxd:
cimport cython
from libcpp cimport bool
cdef extern from *:
"""
typedef struct {
int key;
float a;
float b;
} myType;
bool operator<(const myType t1, const myType t2) {
return t1.key < t2.key;
}
"""
ctypedef struct myType:
int key
float a
float b
Спасибо @ead за помощь
Похожие вопросы
Связанные вопросы
Новые вопросы
containers
Контейнер - это класс, структура данных или абстрактный тип данных, экземплярами которого являются коллекции других объектов. Контейнеры обычно используют универсальные шаблоны или шаблоны, чтобы можно было добавлять самые разные объекты.