litgen provides advanced support for template classes and functions. Refer to the examples below.
Template Functions¶
Relevant portion of the pybind11 manual and of the nanobind manual
litgen can instantiate template functions for a customizable range of types.
Export template functions with an @overload decorator¶
Consider the example below. If we try to generate code from it, litgen will complain that this template function is unhandled:
cpp_code = """
template<typename T> T MaxValue(const std::vector<T>& values);
"""
import litgen
from litgen.demo import litgen_demo
options = litgen.LitgenOptions()
generated_code = litgen.generate_code(options, cpp_code)Warning: (LitgenTemplateFunctionIgnore) Ignoring template function MaxValue. You might need to set LitgenOptions.fn_template_options
While parsing a "function_decl", corresponding to this C++ code:
Position:2:5
template<typename T> T MaxValue(const std::vector<T>& values);
^
Warning: (LitgenTemplateFunctionIgnore) Ignoring template function MaxValue. You might need to set LitgenOptions.fn_template_options
While parsing a "function_decl", corresponding to this C++ code:
Position:2:5
template<typename T> T MaxValue(const std::vector<T>& values);
^
If we add some information about how we want to specialize the function, then litgen will correctly output the bindings, and it will add an @overload decorator to the python functions.
options.fn_template_options.add_specialization("^MaxValue$", ["int", "float"], add_suffix_to_function_name=False)
litgen_demo.demo(options, cpp_code)Export template functions with a suffix¶
Instead of using @overload, we can give different names to the python functions:
cpp_code = """
template<typename T> voi LogValue(const std::string& label, const T& value);
"""
options = litgen.LitgenOptions()
options.fn_template_options.add_specialization("^LogValue$", ["int", "float"], add_suffix_to_function_name=True)
litgen_demo.demo(options, cpp_code)Template classes¶
Introduction¶
Relevant portion of the pybind11 manual and of the nanobind manual
litgen handles template classes instantiation in a sophisticated way.
In the example below, we set the following options:
type replacements
We set an option for type name replacements, so that ImGuiConfig will be exposed as Config in python:
options.type_replacements.add_last_replacement(r"ImGui([A-Z][a-zA-Z0-9]*)", r"\1")class specialization
We tell litgen to instantiate
ImVectorforImGuiConfig,float *, andint32_t.We also tell it to emit a synonym (
ImVector_Int32 = ImVector_int) in the python stub.
options.class_template_options.add_specialization(
"ImVector", # which class do we want to specialize
["ImGuiConfig", "float *", "int32_t"], # for which types
["Int32=uint32_t"] # With which synonyms
)Notes
The member
Foo::Configswill be exposed with the correct python type (ImVector_Config)The member
Foo::IntValueswill not be published, sinceImVector<int>is not publishedlitgen will emit a warning about the missing specialization for
int
Example of template class instantiation¶
cpp_code = """
struct ImGuiConfig { /* implementation not shown here */ };
template<typename T>
struct ImVector
{
// Implementation not shown here
private:
T* data;
};
struct Foo
{
ImVector<ImGuiConfig> Configs; // This member will be added to the bindings
ImVector<int> IntValues; // This member will be excluded from the bindings, since ImVector<int> is not published!
};
"""
options = litgen.LitgenOptions()
options.type_replacements.add_last_replacement(r"ImGui([A-Z][a-zA-Z0-9]*)", r"\1") # Remove prefix ImGui from exposed type
options.class_template_options.add_specialization(
"ImVector", # which class do we want to specialize
["ImGuiConfig", "float *", "int32_t"], # for which types
["Int32=uint32_t"], # With which synonyms
)
litgen_demo.demo(options, cpp_code)
# Note: the warnings below are normal, since we did not specialize ImVector<int> (they can be filtered out, see below)Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Warning: (Undefined) Excluding template type ImVector<int> because its specialization for `int` is not handled
While parsing a "type", corresponding to this C++ code:
Position:16:9
Suppress template class warnings¶
You can ask litgen to ignore the warnings concerning the missing specialization:
# tell litgen to ignore warnings that contain "Excluding template type ImVector<int>"
options.srcmlcpp_options.ignored_warning_parts.append("Excluding template type ImVector<int>")
# the following line emits a warning that is ignored
generated_code = litgen.generate_code(options, cpp_code)