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...
Это как-то возможно? Есть ли другие способы добиться чего-то подобного?