Boost :: Python класс с шаблонами функций: как добавить экземпляры извне?

Резюме

Есть ли способ (в C ++, а не в Python) добавить дополнительные экземпляры шаблонов функций для класса в Boost :: Python извне (путем внедрения, повторного открытия определения, регистрации необходимых экземпляров и т. Д.)?

Фон

Учитывая класс (не шаблон класса), содержащий члены, которые являются шаблонами функций, я хочу генерировать привязки Python, используя Boost :: Python.

Однако, поскольку я пишу библиотеку, я не знаю заранее, с какими параметрами шаблона будут вызываться функции-члены. Это означает, что я не могу перечислить их в определении класса Boost :: Python.

пример

Допустим, у нас есть классTheClass с шаблонами функций (с перегрузками) и двумя тестовыми классамиSomeClass а такжеOtherClass как это:

Определения классов
#include <iostream>
#include <string>

class SomeClass
{
public:
    std::string Name()
    {
        return "SomeClass";
    }
};

class OtherClass
{
public:
    std::string Name()
    {
        return "OtherClass";
    }
};

class TheClass
{
public:

    template <class T>
    void Foo   (T& arg)
    {
        std::cout << "Called Foo(" << arg.Name() << ")" << std::endl;
    }

    template <class T>
    void Bar   (T& arg, std::string param)
    {
        std::cout << "Called Bar(" << arg.Name() << ", " << param << ")" << std::endl;
    }

    template <class T>
    void Bar   (T& arg, int param)
    {
        std::cout << "Called Bar(" << arg.Name() << ", " << param << ")" << std::endl;
    }

};

Затем я использую этот код для экспорта всего вышеперечисленного в Python:

Увеличить экспорт Python
#include <boost/python.hpp>

#define GENERATE_THE_CLASS_METHODS(classname)                                 \
    .def(                                                                     \
        "Foo",                                                                \
        ( void ( TheClass::* )( classname& ))( &TheClass::Foo ),              \
        ( boost::python::arg("arg") )                                         \
    )                                                                         \
    .def(                                                                     \
        "Bar",                                                                \
        ( void ( TheClass::* )( classname&, std::string ))( &TheClass::Bar ), \
        ( boost::python::arg("arg"), boost::python::arg("param") )            \
    )                                                                         \
    .def(                                                                     \
        "Bar",                                                                \
        ( void ( TheClass::* )( classname&, int ))( &TheClass::Bar ),         \
        ( boost::python::arg("arg"), boost::python::arg("param") )            \
    )

BOOST_PYTHON_MODULE(my_module)
{
    boost::python::class_< TheClass > ( "TheClass" )
        GENERATE_THE_CLASS_METHODS(SomeClass)
        GENERATE_THE_CLASS_METHODS(OtherClass)

        // This is the interesting part: all instantiations of the function
        // templates have to be inserted here. How can this be avoided
        // so that new classes can also be used?

    ;

    boost::python::class_< SomeClass > ( "SomeClass" );
    boost::python::class_< OtherClass > ( "OtherClass" );
}

(Дополнительный вопрос: здесь я использую макрос, чтобы избежать дублирования кода по причинам обслуживания. Есть ли более красивый, C ++ - простой способ достижения этого?)

Python Test Script

Приведенный выше код компилируется с использованием Clang с C ++ 11, Boost 1.57.0 и Python 2.7.6. Он работает с этим тестовым скриптом:

#!/usr/bin/python

from my_module import *

s = SomeClass()
o = OtherClass()
t = TheClass()

t.Foo(s)
t.Foo(o)

t.Bar(s, 42)
t.Bar(o, 42)
t.Bar(s, "Hello World")
t.Bar(o, "Hello World")

Выход из этого:

Called Foo(SomeClass)
Called Foo(OtherClass)
Called Bar(SomeClass, 42)
Called Bar(OtherClass, 42)
Called Bar(SomeClass, Hello World)
Called Bar(OtherClass, Hello World)
Вопрос

В этом примере экземпляры шаблонов функций для Foo () и Bar () создаются внутри определения класса Boost :: Python (см. Комментарий в исходном коде). Это означает, что пользователь библиотеки не может добавить новый экземпляр без изменения этого бита кода.

Таким образом, то, что я ищу, это способ либо

«внедрить» эти экземпляры извне определения класса Boost :: Pythonзаново открыть определение как-тозарегистрируйте необходимые экземпляры где-нибудь перед вызовом определения класса Boost :: Python

В конце пользователь библиотеки должен иметь возможность сделать что-то вроде этого:

class AnotherClass
{
public:
    std::string Name()
    {
        return "AnotherClass";
    }
};

add_to_the_class(AnotherClass);
// or
add_to_class_definition<AnotherClass>("TheClass");
// or whatever works...

Это как-то возможно? Есть ли другие способы добиться чего-то подобного?

Ответы на вопрос(1)

Ваш ответ на вопрос