-
Notifications
You must be signed in to change notification settings - Fork 14
Description
I have a class of the form:
template <typename T> class Bezier {
public:
/**
* @brief Unweighted cubic bezier configuration for 4 control points.
*/
struct Config {
std::array<T, 4> control_points; ///< Array of 4 control points
};
/**
* @brief Weighted cubic bezier configuration for 4 control points with
* individual weights.
*/
struct WeightedConfig {
std::array<T, 4> control_points; ///< Array of 4 control points
std::array<float, 4> weights = {1.0f, 1.0f, 1.0f,
1.0f}; ///< Array of 4 weights, default is array of 1.0f
};
/**
* @brief Construct an unweighted cubic bezier curve for evaluation.
* @param config Unweighted Config structure containing the control points.
*/
explicit Bezier(const Config &config)
: weighted_(false)
, control_points_(config.control_points) {}
/**
* @brief Construct a rational / weighted cubic bezier curve for evaluation.
* @param config Rational / weighted WeightedConfig structure containing the
* control points and their weights.
*/
explicit Bezier(const WeightedConfig &config)
: weighted_(true)
, control_points_(config.control_points)
, weights_(config.weights) {}Which (when configured with the options to specialize), generates the following binding code:
//////////////////// <generated_from:bezier.hpp> ////////////////////
auto pyClassBezier_espp_Vector2f =
py::class_<espp::Bezier<espp::Vector2f>>
(m, "Bezier_espp_Vector2f", py::dynamic_attr(), "*\n * @brief Implements rational / weighted and unweighted cubic bezier curves\n * between control points.\n * @note See https://pomax.github.io/bezierinfo/ for information on bezier\n * curves.\n * @note Template class which can be used individually on floating point\n * values directly or on containers such as Vector2<float>.\n * @tparam T The type of the control points, e.g. float or Vector2<float>.\n * @note The bezier curve is defined by 4 control points, P0, P1, P2, P3.\n * The curve is defined by the equation:\n * \\f$B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P3\\f$\n * where t is the evaluation parameter, [0, 1].\n *\n * @note The weighted bezier curve is defined by 4 control points, P0, P1, P2, P3\n * and 4 weights, W0, W1, W2, W3.\n * The curve is defined by the equation:\n * \\f$B(t) = (W0 * (1-t)^3 * P0 + W1 * 3 * (1-t)^2 * t * P1 + W2 * 3 * (1-t) * t^2 * P2 + W3 *\n * t^3 * P3) / (W0 + W1 + W2 + W3)\\f$ where t is the evaluation parameter, [0, 1].\n *\n * \\section bezier_ex1 Example\n * \\snippet math_example.cpp bezier example\n");
{ // inner classes & enums of Bezier_espp_Vector2f
auto pyClassBezier_ClassConfig =
py::class_<espp::Bezier::Config>
(pyClassBezier, "Config", py::dynamic_attr(), "*\n * @brief Unweighted cubic bezier configuration for 4 control points.\n")
.def(py::init<>()) // implicit default constructor
.def_readwrite("control_points", &espp::Bezier::Config::control_points, "/< Array of 4 control points")
;
auto pyClassBezier_ClassWeightedConfig =
py::class_<espp::Bezier::WeightedConfig>
(pyClassBezier, "WeightedConfig", py::dynamic_attr(), "*\n * @brief Weighted cubic bezier configuration for 4 control points with\n * individual weights.\n")
.def(py::init<>()) // implicit default constructor
.def_readwrite("control_points", &espp::Bezier::WeightedConfig::control_points, "/< Array of 4 control points")
.def_readwrite("weights", &espp::Bezier::WeightedConfig::weights, "/< Array of 4 weights, default is array of 1.0")
;
} // end of inner classes & enums of Bezier_espp_Vector2f
pyClassBezier_espp_Vector2f
.def(py::init<>()) // implicit default constructor
.def("__call__",
&espp::Bezier<espp::Vector2f>::operator(),
py::arg("t"),
"*\n * @brief Evaluate the bezier at \\p t.\n * @note Convienience wrapper around the at() method.\n * @param t The evaluation parameter, [0, 1].\n * @return The bezier evaluated at \\p t.\n")
;
//////////////////// </generated_from:bezier.hpp> ////////////////////There are two errors here:
- It incorrectly generates the
implicit default constructor, and - It does not properly generate the explicit constructors that are defined in the class.
This is not related to #14 (template specialization issue), as it also occurs on other classes I have which are not template classes but which also lack a default constructor and instead have explicit non-zero parameter constructors.
I've done some initial instrumentation in the python code to determine why this might be the case, and I'm seeing that it's properly setting flag_generate_void_ctor to false, and flag_generate_named_ctor_params to true, but for some reason (which I haven't figured out yet), it is unable to actually get the parameters for the constructor - instead returning a ctor_decl for which len(ctor_decl.parameter_list.parameters) == 0.