boost-python - предоставляет C ++ (не чистый) виртуальный метод с аргументами по умолчанию

Это чистое решение для JavaScript без каких-либо библиотек или плагинов:

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

, где hasClass -

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

Live demo

Кредит относится к Dave и Sime Vidas

Использование более современных JS, hasClass может быть реализовано как:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}

0
задан Phil 29 March 2019 в 18:22
поделиться

1 ответ

Я собрал воедино решение, которое, кажется, работает и подчиняется правилам полиморфизма.

Секрет в том, чтобы просто вообще не использовать макрос boost::python::args или BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS (хотя я допускаю, что он не будет поддерживать аргументы ключ-значение в Python как есть).

Просто создайте вспомогательную функцию, которая имеет l-значение, совпадающее с классом, содержащим виртуальную функцию, т.е. X, и не имеет НИКАКИХ других аргументов, переданных ей. Это избавляет от проблемы Python, не соответствующей сигнатуре метода, потому что параметр a вместе со значением по умолчанию просто не существует:

A* getItem_noargs_wrap(X& x)
{
    return x.getItem();
}

Это кажется бессмысленным, но это совсем не так. Вызов x.getItem() - от C ++ до C ++, поэтому параметр по умолчанию правильно сопоставляется с пустой подписью.

Однако, когда мы пришли к написанию нашего def(), мы теперь можем дать Python функцию, которая действительно не принимает аргументов, что позволяет ему соответствовать вызовам getItem() в Python.

Осталось лишь немного помочь компилятору узнать, какая сигнатура соответствует какому базовому вызову:

.def("getItem",                                                                                                                                                                                                                                      
     &getItem_noargs_wrap);
.def("getItem",                                                                                                                                                                                                                                      
     &X::getItem,                                                                                                                                                                                                                   
     &X_wrap::default_getItem);

Так что getItem() дважды предоставляется Python - один раз без аргументов используя нашу вспомогательную функцию для вызова метода правильного экземпляра за кулисами, и однажды взяв Z* и используя стандартный шаблон для не чистых виртуальных функций.

Второй вызов - сопоставление в действии:

.def<const char* (X::*)(Z*)>("getItem",

Это, кажется, работает хорошо - но я не исчерпывающе проверил, что он каким-то образом не нарушает полиморфизм. 1121]

0
ответ дан Phil 29 March 2019 в 18:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: