Skip to content

[ENH] Avoid need for C++ default constructors #4160

@da-woods

Description

@da-woods

Is your feature request related to a problem? Please describe.

Currently stack allocated C++ classes and temps require default constructors since they're initialized at the start of the function.

cdef extern from *:
    cdef cppclass Someclass:
        pass
    SomeClass func() except +

def f(make_someclass: bool):
   if make_someclass:
      a = func()

this generates code along the lines of:

PyObject* f(...) {
   Someclass a
   Someclass __pyx_t_1;
   if (make_someclass) {
      try {
          __pyx_t_1 = make_someclass();
      } catch (...) {
           // exception handling here
      }
      a = __PYX_MOVE_IF_POSSIBLE(__pyx_t_1);
   }
}

This puts restrictions on what c++ types can be used on the stack (or even as return types of functions, because of the temps creates)

Describe the solution you'd like

std::optional provides a way around this. It'd be possible to create the stack variables as:

std::optional<Someclass> a;
std::optional<Someclass> __pyx_t_1;

These keep keep track of whether it's been assigned, and handle destruction etc. as needed.

My proposal is that this should be an opt-in feature, controlled by a directive. There's a number of good reasons not to do it by default:

  • C++17 only (which is a fairly hefty requirement)
  • Potential performance changes (due to extra space usage, and "initialized tests"
  • Changes in Cython behaviour - accessing an uninitialized C++ variable becomes a potential crash rather than an access to a valid default-initialized object.

I think the Cython type system would have to know about the std::optional and treat them as a slightly different type to the raw classes - *optional gets to the underlying class, which is a trivial coercion, but one that can't happen automatically.

Describe alternatives you've considered

The status quo.

Reimplement std::optional (i.e. it's a library feature, I don't think it requires a significant compiler support). That would reduce the compiler requirement, but require more effort. It could also be implemented in terms of std::optional first then revisited if need.

Additional context

Exceptions from constructors/operators are a potential problem. But equally exceptions from default/copy/move constructors/operators are an issue in Cython currently.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions