mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-31 15:20:34 +00:00
Merge pull request #381 from jagerman/tests-self-registering
Make test initialization self-registering
This commit is contained in:
commit
2ea4b8e8bb
@ -7,6 +7,7 @@ set(PYBIND11_TEST_FILES
|
||||
test_buffers.cpp
|
||||
test_callbacks.cpp
|
||||
test_constants_and_functions.cpp
|
||||
test_eigen.cpp
|
||||
test_enum.cpp
|
||||
test_eval.cpp
|
||||
test_exceptions.cpp
|
||||
@ -28,14 +29,21 @@ set(PYBIND11_TEST_FILES
|
||||
test_virtual_functions.cpp
|
||||
)
|
||||
|
||||
# Check if Eigen is available
|
||||
find_package(Eigen3 QUIET)
|
||||
string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
|
||||
|
||||
if(EIGEN3_FOUND)
|
||||
list(APPEND PYBIND11_TEST_FILES test_eigen.cpp)
|
||||
message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
|
||||
else()
|
||||
message(STATUS "Building tests WITHOUT Eigen")
|
||||
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
|
||||
# keep it in PYBIND11_PYTEST_FILES, so that we get the "eigen is not installed"
|
||||
# skip message).
|
||||
list(FIND PYBIND11_TEST_FILES test_eigen.cpp PYBIND11_TEST_FILES_EIGEN_I)
|
||||
if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
|
||||
find_package(Eigen3 QUIET)
|
||||
|
||||
if(EIGEN3_FOUND)
|
||||
message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
|
||||
else()
|
||||
list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I})
|
||||
message(STATUS "Building tests WITHOUT Eigen")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create the binding library
|
||||
@ -74,5 +82,5 @@ if(NOT PYBIND11_PYTEST_FOUND)
|
||||
endif()
|
||||
|
||||
# A single command to compile and run the tests
|
||||
add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws
|
||||
add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws ${PYBIND11_PYTEST_FILES}
|
||||
DEPENDS pybind11_tests WORKING_DIRECTORY ${testdir})
|
||||
|
@ -10,32 +10,14 @@
|
||||
#include "pybind11_tests.h"
|
||||
#include "constructor_stats.h"
|
||||
|
||||
void init_ex_methods_and_attributes(py::module &);
|
||||
void init_ex_python_types(py::module &);
|
||||
void init_ex_operator_overloading(py::module &);
|
||||
void init_ex_constants_and_functions(py::module &);
|
||||
void init_ex_callbacks(py::module &);
|
||||
void init_ex_sequences_and_iterators(py::module &);
|
||||
void init_ex_buffers(py::module &);
|
||||
void init_ex_smart_ptr(py::module &);
|
||||
void init_ex_modules(py::module &);
|
||||
void init_ex_numpy_vectorize(py::module &);
|
||||
void init_ex_arg_keywords_and_defaults(py::module &);
|
||||
void init_ex_virtual_functions(py::module &);
|
||||
void init_ex_keep_alive(py::module &);
|
||||
void init_ex_opaque_types(py::module &);
|
||||
void init_ex_pickling(py::module &);
|
||||
void init_ex_inheritance(py::module &);
|
||||
void init_ex_stl_binder_vector(py::module &);
|
||||
void init_ex_eval(py::module &);
|
||||
void init_ex_custom_exceptions(py::module &);
|
||||
void init_ex_numpy_dtypes(py::module &);
|
||||
void init_ex_enum(py::module &);
|
||||
void init_issues(py::module &);
|
||||
std::list<std::function<void(py::module &)>> &initializers() {
|
||||
static std::list<std::function<void(py::module &)>> inits;
|
||||
return inits;
|
||||
}
|
||||
|
||||
#if defined(PYBIND11_TEST_EIGEN)
|
||||
void init_eigen(py::module &);
|
||||
#endif
|
||||
test_initializer::test_initializer(std::function<void(py::module &)> initializer) {
|
||||
initializers().push_back(std::move(initializer));
|
||||
}
|
||||
|
||||
void bind_ConstructorStats(py::module &m) {
|
||||
py::class_<ConstructorStats>(m, "ConstructorStats")
|
||||
@ -54,35 +36,10 @@ PYBIND11_PLUGIN(pybind11_tests) {
|
||||
|
||||
bind_ConstructorStats(m);
|
||||
|
||||
init_ex_methods_and_attributes(m);
|
||||
init_ex_python_types(m);
|
||||
init_ex_operator_overloading(m);
|
||||
init_ex_constants_and_functions(m);
|
||||
init_ex_callbacks(m);
|
||||
init_ex_sequences_and_iterators(m);
|
||||
init_ex_buffers(m);
|
||||
init_ex_smart_ptr(m);
|
||||
init_ex_modules(m);
|
||||
init_ex_numpy_vectorize(m);
|
||||
init_ex_arg_keywords_and_defaults(m);
|
||||
init_ex_virtual_functions(m);
|
||||
init_ex_keep_alive(m);
|
||||
init_ex_opaque_types(m);
|
||||
init_ex_pickling(m);
|
||||
init_ex_inheritance(m);
|
||||
init_ex_stl_binder_vector(m);
|
||||
init_ex_eval(m);
|
||||
init_ex_custom_exceptions(m);
|
||||
init_ex_numpy_dtypes(m);
|
||||
init_ex_enum(m);
|
||||
init_issues(m);
|
||||
for (const auto &initializer : initializers())
|
||||
initializer(m);
|
||||
|
||||
#if defined(PYBIND11_TEST_EIGEN)
|
||||
init_eigen(m);
|
||||
m.attr("have_eigen") = py::cast(true);
|
||||
#else
|
||||
m.attr("have_eigen") = py::cast(false);
|
||||
#endif
|
||||
if (!m.attr("have_eigen")) m.attr("have_eigen") = py::cast(false);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
#pragma once
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
class test_initializer {
|
||||
public:
|
||||
test_initializer(std::function<void(py::module &)> initializer);
|
||||
};
|
||||
|
@ -74,7 +74,7 @@ private:
|
||||
float *m_data;
|
||||
};
|
||||
|
||||
void init_ex_buffers(py::module &m) {
|
||||
test_initializer buffers([](py::module &m) {
|
||||
py::class_<Matrix> mtx(m, "Matrix");
|
||||
|
||||
mtx.def(py::init<size_t, size_t>())
|
||||
@ -114,4 +114,4 @@ void init_ex_buffers(py::module &m) {
|
||||
);
|
||||
})
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ struct Payload {
|
||||
}
|
||||
};
|
||||
|
||||
void init_ex_callbacks(py::module &m) {
|
||||
test_initializer callbacks([](py::module &m) {
|
||||
m.def("test_callback1", &test_callback1);
|
||||
m.def("test_callback2", &test_callback2);
|
||||
m.def("test_callback3", &test_callback3);
|
||||
@ -95,4 +95,4 @@ void init_ex_callbacks(py::module &m) {
|
||||
m.def("test_dummy_function", &test_dummy_function);
|
||||
// Export the payload constructor statistics for testing purposes:
|
||||
m.def("payload_cstats", &ConstructorStats::get<Payload>);
|
||||
}
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ std::string print_bytes(py::bytes bytes) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void init_ex_constants_and_functions(py::module &m) {
|
||||
test_initializer constants_and_functions([](py::module &m) {
|
||||
m.attr("some_constant") = py::int_(14);
|
||||
|
||||
m.def("test_function", &test_function1);
|
||||
@ -52,4 +52,4 @@ void init_ex_constants_and_functions(py::module &m) {
|
||||
|
||||
m.def("return_bytes", &return_bytes);
|
||||
m.def("print_bytes", &print_bytes);
|
||||
}
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Ma
|
||||
MatrixXfRowMajor double_mat_rm(const MatrixXfRowMajor& x)
|
||||
{ return 2.0f * x; }
|
||||
|
||||
void init_eigen(py::module &m) {
|
||||
test_initializer eigen([](py::module &m) {
|
||||
typedef Eigen::Matrix<float, 5, 6, Eigen::RowMajor> FixedMatrixR;
|
||||
typedef Eigen::Matrix<float, 5, 6> FixedMatrixC;
|
||||
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> DenseMatrixR;
|
||||
@ -40,6 +40,8 @@ void init_eigen(py::module &m) {
|
||||
typedef Eigen::SparseMatrix<float, Eigen::RowMajor> SparseMatrixR;
|
||||
typedef Eigen::SparseMatrix<float> SparseMatrixC;
|
||||
|
||||
m.attr("have_eigen") = py::cast(true);
|
||||
|
||||
// Non-symmetric matrix with zero elements
|
||||
Eigen::MatrixXf mat(5, 6);
|
||||
mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0,
|
||||
@ -129,4 +131,4 @@ void init_eigen(py::module &m) {
|
||||
m.def("sparse_passthrough_c", [](const SparseMatrixC &m) -> SparseMatrixC {
|
||||
return m;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ std::string test_scoped_enum(ScopedEnum z) {
|
||||
return "ScopedEnum::" + std::string(z == ScopedEnum::Two ? "Two" : "Three");
|
||||
}
|
||||
|
||||
void init_ex_enum(py::module &m) {
|
||||
test_initializer enums([](py::module &m) {
|
||||
m.def("test_scoped_enum", &test_scoped_enum);
|
||||
|
||||
py::enum_<UnscopedEnum>(m, "UnscopedEnum")
|
||||
@ -54,4 +54,4 @@ void init_ex_enum(py::module &m) {
|
||||
.value("EFirstMode", ClassWithUnscopedEnum::EFirstMode)
|
||||
.value("ESecondMode", ClassWithUnscopedEnum::ESecondMode)
|
||||
.export_values();
|
||||
}
|
||||
});
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <pybind11/eval.h>
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
void init_ex_eval(py::module & m) {
|
||||
test_initializer eval([](py::module &m) {
|
||||
auto global = py::dict(py::module::import("__main__").attr("__dict__"));
|
||||
|
||||
m.def("test_eval_statements", [global]() {
|
||||
@ -77,4 +77,4 @@ void init_ex_eval(py::module & m) {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ void throws_logic_error() {
|
||||
throw std::logic_error("this error should fall through to the standard handler");
|
||||
}
|
||||
|
||||
void init_ex_custom_exceptions(py::module &m) {
|
||||
test_initializer custom_exceptions([](py::module &m) {
|
||||
// make a new custom exception and use it as a translation target
|
||||
static py::exception<MyException> ex(m, "MyException");
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
@ -104,5 +104,5 @@ void init_ex_custom_exceptions(py::module &m) {
|
||||
m.def("throws3", &throws3);
|
||||
m.def("throws4", &throws4);
|
||||
m.def("throws_logic_error", &throws_logic_error);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct BaseClass { virtual ~BaseClass() {} };
|
||||
struct DerivedClass1 : BaseClass { };
|
||||
struct DerivedClass2 : BaseClass { };
|
||||
|
||||
void init_ex_inheritance(py::module &m) {
|
||||
test_initializer inheritance([](py::module &m) {
|
||||
py::class_<Pet> pet_class(m, "Pet");
|
||||
pet_class
|
||||
.def(py::init<std::string, std::string>())
|
||||
@ -69,4 +69,4 @@ void init_ex_inheritance(py::module &m) {
|
||||
m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
|
||||
m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
|
||||
m.def("return_none", []() -> BaseClass* { return nullptr; });
|
||||
}
|
||||
});
|
||||
|
@ -173,3 +173,6 @@ void init_issues(py::module &m) {
|
||||
m2.def("get_NestB", [](const NestB &b) { return b.value; });
|
||||
m2.def("get_NestC", [](const NestC &c) { return c.value; });
|
||||
}
|
||||
|
||||
// MSVC workaround: trying to use a lambda here crashes MSCV
|
||||
test_initializer issues(&init_issues);
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
Child *returnNullChild() { return nullptr; }
|
||||
};
|
||||
|
||||
void init_ex_keep_alive(py::module &m) {
|
||||
test_initializer keep_alive([](py::module &m) {
|
||||
py::class_<Parent>(m, "Parent")
|
||||
.def(py::init<>())
|
||||
.def("addChild", &Parent::addChild)
|
||||
@ -37,4 +37,4 @@ void init_ex_keep_alive(py::module &m) {
|
||||
|
||||
py::class_<Child>(m, "Child")
|
||||
.def(py::init<>());
|
||||
}
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ struct KWClass {
|
||||
void foo(int, float) {}
|
||||
};
|
||||
|
||||
void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
test_initializer arg_keywords_and_defaults([](py::module &m) {
|
||||
m.def("kw_func0", &kw_func);
|
||||
m.def("kw_func1", &kw_func, py::arg("x"), py::arg("y"));
|
||||
m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200);
|
||||
@ -63,4 +63,4 @@ void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
py::class_<KWClass>(m, "KWClass")
|
||||
.def("foo0", &KWClass::foo)
|
||||
.def("foo1", &KWClass::foo, "x"_a, "y"_a);
|
||||
}
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
void init_ex_methods_and_attributes(py::module &m) {
|
||||
test_initializer methods_and_attributes([](py::module &m) {
|
||||
py::class_<ExampleMandA>(m, "ExampleMandA")
|
||||
.def(py::init<>())
|
||||
.def(py::init<int>())
|
||||
@ -81,4 +81,4 @@ void init_ex_methods_and_attributes(py::module &m) {
|
||||
.def("__str__", &ExampleMandA::toString)
|
||||
.def_readwrite("value", &ExampleMandA::value)
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
A a2{2};
|
||||
};
|
||||
|
||||
void init_ex_modules(py::module &m) {
|
||||
test_initializer modules([](py::module &m) {
|
||||
py::module m_sub = m.def_submodule("submodule");
|
||||
m_sub.def("submodule_func", &submodule_func);
|
||||
|
||||
@ -55,4 +55,4 @@ void init_ex_modules(py::module &m) {
|
||||
.def_readwrite("a2", &B::a2);
|
||||
|
||||
m.attr("OD") = py::module::import("collections").attr("OrderedDict");
|
||||
}
|
||||
});
|
||||
|
@ -267,7 +267,7 @@ py::list test_dtype_methods() {
|
||||
return list;
|
||||
}
|
||||
|
||||
void init_ex_numpy_dtypes(py::module &m) {
|
||||
test_initializer numpy_dtypes([](py::module &m) {
|
||||
try {
|
||||
py::module::import("numpy");
|
||||
} catch (...) {
|
||||
@ -297,6 +297,6 @@ void init_ex_numpy_dtypes(py::module &m) {
|
||||
m.def("test_array_ctors", &test_array_ctors);
|
||||
m.def("test_dtype_ctors", &test_dtype_ctors);
|
||||
m.def("test_dtype_methods", &test_dtype_methods);
|
||||
}
|
||||
});
|
||||
|
||||
#undef PYBIND11_PACKED
|
||||
|
@ -20,7 +20,7 @@ std::complex<double> my_func3(std::complex<double> c) {
|
||||
return c * std::complex<double>(2.f);
|
||||
}
|
||||
|
||||
void init_ex_numpy_vectorize(py::module &m) {
|
||||
test_initializer numpy_vectorize([](py::module &m) {
|
||||
// Vectorize all arguments of a function (though non-vector arguments are also allowed)
|
||||
m.def("vectorized_func", py::vectorize(my_func));
|
||||
|
||||
@ -38,4 +38,4 @@ void init_ex_numpy_vectorize(py::module &m) {
|
||||
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { return "Int branch taken."; });
|
||||
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { return "Float branch taken."; });
|
||||
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { return "Complex float branch taken."; });
|
||||
}
|
||||
});
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
/* IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures */
|
||||
PYBIND11_MAKE_OPAQUE(StringList);
|
||||
|
||||
void init_ex_opaque_types(py::module &m) {
|
||||
test_initializer opaque_types([](py::module &m) {
|
||||
py::class_<StringList>(m, "StringList")
|
||||
.def(py::init<>())
|
||||
.def("pop_back", &StringList::pop_back)
|
||||
@ -59,4 +59,4 @@ void init_ex_opaque_types(py::module &m) {
|
||||
result->push_back("some value");
|
||||
return std::unique_ptr<StringList>(result);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -52,7 +52,7 @@ private:
|
||||
float x, y;
|
||||
};
|
||||
|
||||
void init_ex_operator_overloading(py::module &m) {
|
||||
test_initializer operator_overloading([](py::module &m) {
|
||||
py::class_<Vector2>(m, "Vector2")
|
||||
.def(py::init<float, float>())
|
||||
.def(py::self + py::self)
|
||||
@ -73,4 +73,4 @@ void init_ex_operator_overloading(py::module &m) {
|
||||
;
|
||||
|
||||
m.attr("Vector") = m.attr("Vector2");
|
||||
}
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ private:
|
||||
int m_extra2 = 0;
|
||||
};
|
||||
|
||||
void init_ex_pickling(py::module &m) {
|
||||
test_initializer pickling([](py::module &m) {
|
||||
py::class_<Pickleable>(m, "Pickleable")
|
||||
.def(py::init<std::string>())
|
||||
.def("value", &Pickleable::value)
|
||||
@ -48,4 +48,4 @@ void init_ex_pickling(py::module &m) {
|
||||
p.setExtra1(t[1].cast<int>());
|
||||
p.setExtra2(t[2].cast<int>());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
int ExamplePythonTypes::value = 0;
|
||||
const int ExamplePythonTypes::value2 = 5;
|
||||
|
||||
void init_ex_python_types(py::module &m) {
|
||||
test_initializer python_types([](py::module &m) {
|
||||
/* No constructor is explicitly defined below. An exception is raised when
|
||||
trying to construct it directly from Python */
|
||||
py::class_<ExamplePythonTypes>(m, "ExamplePythonTypes", "Example 2 documentation")
|
||||
@ -197,4 +197,4 @@ void init_ex_python_types(py::module &m) {
|
||||
.def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member")
|
||||
.def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)")
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -168,7 +168,7 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine
|
||||
return !(*it).first || !(*it).second;
|
||||
}
|
||||
|
||||
void init_ex_sequences_and_iterators(py::module &m) {
|
||||
test_initializer sequences_and_iterators([](py::module &m) {
|
||||
|
||||
py::class_<Sequence> seq(m, "Sequence");
|
||||
|
||||
@ -271,4 +271,4 @@ void init_ex_sequences_and_iterators(py::module &m) {
|
||||
On the actual Sequence object, the iterator would be constructed as follows:
|
||||
.def("__iter__", [](py::object s) { return PySequenceIterator(s.cast<const Sequence &>(), s); })
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
@ -105,7 +105,7 @@ void print_myobject3_2(std::shared_ptr<MyObject3> obj) { std::cout << obj->toStr
|
||||
void print_myobject3_3(const std::shared_ptr<MyObject3> &obj) { std::cout << obj->toString() << std::endl; }
|
||||
void print_myobject3_4(const std::shared_ptr<MyObject3> *obj) { std::cout << (*obj)->toString() << std::endl; }
|
||||
|
||||
void init_ex_smart_ptr(py::module &m) {
|
||||
test_initializer smart_ptr([](py::module &m) {
|
||||
py::class_<Object, ref<Object>> obj(m, "Object");
|
||||
obj.def("getRefCount", &Object::getRefCount);
|
||||
|
||||
@ -147,4 +147,4 @@ void init_ex_smart_ptr(py::module &m) {
|
||||
|
||||
// Expose constructor stats for the ref type
|
||||
m.def("cstats_ref", &ConstructorStats::get<ref_tag>);
|
||||
}
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ std::ostream & operator<<(std::ostream &s, El const&v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
void init_ex_stl_binder_vector(py::module &m) {
|
||||
test_initializer stl_binder_vector([](py::module &m) {
|
||||
py::class_<El>(m, "El")
|
||||
.def(py::init<int>());
|
||||
|
||||
@ -34,4 +34,4 @@ void init_ex_stl_binder_vector(py::module &m) {
|
||||
py::bind_vector<El>(m, "VectorEl");
|
||||
|
||||
py::bind_vector<std::vector<El>>(m, "VectorVectorEl");
|
||||
}
|
||||
});
|
||||
|
@ -283,7 +283,7 @@ void initialize_inherited_virtuals(py::module &m) {
|
||||
};
|
||||
|
||||
|
||||
void init_ex_virtual_functions(py::module &m) {
|
||||
test_initializer virtual_functions([](py::module &m) {
|
||||
/* Important: indicate the trampoline class PyExampleVirt using the third
|
||||
argument to py::class_. The second argument with the unique pointer
|
||||
is simply the default holder type used by pybind11. */
|
||||
@ -315,4 +315,4 @@ void init_ex_virtual_functions(py::module &m) {
|
||||
|
||||
m.def("cstats_debug", &ConstructorStats::get<ExampleVirt>);
|
||||
initialize_inherited_virtuals(m);
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user