2013-08-29 24 views
5

Chciałbym powiązać operatora() za pomocą Boost :: Python, ale tak naprawdę nie widzę, jak to zrobić. Rozważmy przykład:Przyspieszenie operatora przeciążenia Pythona()

C++:

class Queuer 
{ 

public: 
void Queuer::operator()(const qfc::Queue & iq, const qfc::Message & im) const; 
void Queuer::operator()(const qfc::Agent & ia, const qfc::Message & im) const; 
// some other overloaded operator() methods 

}; 

Więc w skrypt Pythona, po zaimportowaniu modułu używam (tzw QFC), chciałbym zrobić:

Python:

>>> queuer = qfc.Queuer() 
// instantiating a Message an Agent and a Queue object 
>>> queuer(queue,message) 
>>> queuer(agent,message) 
>>> ... 

Czy masz pojęcie, jak to zrobić? może z boost :: python zadzwoń <>?

Dziękuję Kevin

Odpowiedz

7

Podczas wystawiania klasę Queuer zdefiniuj __call__ metody dla każdej funkcji Queuer::operator() członkowskim. Boost.Python obsłuży odpowiednią dyspozycję na podstawie typów. Jedyna złożoność jest wprowadzana za pomocą składni funkcji wskaźnik-do-członka, ponieważ wywołujący musi odjednoczyć &Queuer::operator().

Dodatkowo, gdy próbuje przekazać klasy pochodnych Pythona do C funkcji ++ z parametrem klasy bazowej, a następnie pewne dodatkowe informacje muszą być wystawione na Boost.Python:

  • Podstawa C++ wymagania klasy do ujawnienia z class_. Na przykład class_<BaseType>("Base").
  • Klasa pochodna musi jawnie wymieniać swoje klasy bazowe, gdy zostanie ujawniona przy użyciu bases_. Na przykład: class_<DerivedType, bases<BaseType> >("Derived"). Dzięki tym informacjom Boost.Python może wykonać odpowiednie odlewanie podczas wysyłki.

Powyżej znajduje się pełna przykład:

#include <iostream> 

#include <boost/python.hpp> 

// Mockup classes. 
struct AgentBase {}; 
struct MessageBase {}; 
struct QueueBase {}; 
struct SpamBase {}; 
struct Agent: AgentBase {}; 
struct Message: MessageBase {}; 
struct Queue: QueueBase {}; 
struct Spam: SpamBase {}; 

// Class with overloaded operator(). 
class Queuer 
{ 
public: 

    void operator()(const AgentBase&, const MessageBase&) const 
    { 
    std::cout << "Queuer::operator() with Agent." << std::endl; 
    } 

    void operator()(const QueueBase&, const MessageBase&) const 
    { 
    std::cout << "Queuer::operator() with Queue." << std::endl; 
    } 

    void operator()(const SpamBase&, const MessageBase&) const 
    { 
    std::cout << "Queuer::operator() with Spam." << std::endl; 
    } 
}; 

/// Depending on the overlaod signatures, helper types may make the 
/// code slightly more readable by reducing pointer-to-member-function syntax. 
template <typename A1> 
struct queuer_overload 
{ 
    typedef void (Queuer::*type)(const A1&, const MessageBase&) const; 
    static type get(type fn) { return fn; } 
}; 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    // Expose only the base class types. Do not allow the classes to be 
    // directly initialized in Python. 
    python::class_<AgentBase >("AgentBase", python::no_init); 
    python::class_<MessageBase>("MessageBase", python::no_init); 
    python::class_<QueueBase >("QueueBase", python::no_init); 
    python::class_<SpamBase >("SpamBase", python::no_init); 

    // Expose the user types. These classes inerit from their respective 
    // base classes. 
    python::class_<Agent, python::bases<AgentBase> >("Agent"); 
    python::class_<Message, python::bases<MessageBase> >("Message"); 
    python::class_<Queue, python::bases<QueueBase> >("Queue"); 
    python::class_<Spam, python::bases<SpamBase> >("Spam"); 

    // Disambiguate via a varaible. 
    queuer_overload<AgentBase>::type queuer_op_agent = &Queuer::operator(); 

    python::class_<Queuer>("Queuer") 
    // Disambiguate via a variable. 
    .def("__call__", queuer_op_agent) 
    // Disambiguate via a helper type. 
    .def("__call__", queuer_overload<QueueBase>::get(&Queuer::operator())) 
    // Disambiguate via explicit cast. 
    .def("__call__", 
     static_cast<void (Queuer::*)(const SpamBase&, 
             const MessageBase&) const>(
      &Queuer::operator())) 
    ; 
} 

I jego użycie:

>>> import example 
>>> queuer = example.Queuer() 
>>> queuer(example.Agent(), example.Message()) 
Queuer::operator() with Agent. 
>>> queuer(example.Queue(), example.Message()) 
Queuer::operator() with Queue. 
>>> queuer(example.Spam(), example.Message()) 
Queuer::operator() with Spam. 
0

Dzięki za pomoc.

Właściwie testowałem już rozwiązanie statyczne od . W rzeczywistości podczas wywoływania queuer() muszę przekazać qfc::lqs::Message lub qfc::lqs::Agent lub qfc::lqs::Spam. qfc::lqs::Message na przykład, jak dla qfc::lqs::Agent dziedziczy po odpowiednio qfc::Message i qfc::Agent.

Więc mogę "cast" qfc::lqs::Message, qfc::lqs::Agent i qfc::lqs::Spam do qfc::Message, qfc::Agent i qfc::Spam podczas wywoływania operatora() tak, że podpis odpowiada operator()?

to, aby uniknąć błędu pokazano poniżej:

error: invalid static_cast from type '<unresolved overloaded function type>' to type 'void (qfc::lqs::Queuer::*)(const qfc::lqs::Queue&, const qfc::lqs::Message&)const' 
+1

Rozważmy edycji oryginalne pytanie z tej informacji dla przyszłych użytkowników, których napotkasz to pytanie. Ponadto zaktualizowałem odpowiedź na podstawie tego, co według mnie jest zgodne z większą ilością pytania.Jeśli źle zrozumiałem pytanie, nie krępuj się rozszerzać. –

Powiązane problemy