Skip to content

Conversation

guitargeek
Copy link
Contributor

The vector<T> const& constructor needs to be disabled if T is not a const type, because we don't want to create span<T> from vector<T> const&. The explicit disabling via SFINAE is necessary to this overload is not accidentally taken by cppyy, resulting in the failure of constructor wrapper code compilation.

Avoids errors like these when compiling ROOT with C++17:

In module 'Core':
/home/rembserj/code/root/root_install/include/ROOT/span.hxx:208:27: error: cannot initialize a member subobject of type 'pointer' (aka 'double *') with an rvalue of type 'const double *'
     : length_(v.size()), data_(v.empty() ? nullptr : v.data())
                          ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
input_line_45:7:41: note: in instantiation of member function 'std::span<double>::span' requested here
      (*(std::span<double>**)ret) = new std::span<double>((const std::vector<double, std::allocator<double> >&)*(const std::vector<double, std::allocator<double> >*)args[0]);
                                        ^
0
1
2
3

Reproducer:

import ROOT

ROOT.gInterpreter.Declare("""
void calc_cumsum(std::size_t n, std::span<double> v)
{
    for (int i = 0; i < n; i += 1) {
        std::cout << v[i] << std::endl;
    }
}
""")

v = ROOT.std.vector["double"](list(range(4)))

ROOT.calc_cumsum(len(v), v)

The `vector<T> const&` constructor needs to be disabled if T is not a
const type, because we don't want to create `span<T>` from `vector<T>
const&`. The explicit disabling via SFINAE is necessary to this overload
is not accidentally taken by cppyy, resulting in the failure of
constructor wrapper code compilation.

Avoids errors like these when compiling ROOT with C++17:

```txt
In module 'Core':
/home/rembserj/code/root/root_install/include/ROOT/span.hxx:208:27: error: cannot initialize a member subobject of type 'pointer' (aka 'double *') with an rvalue of type 'const double *'
     : length_(v.size()), data_(v.empty() ? nullptr : v.data())
                          ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
input_line_45:7:41: note: in instantiation of member function 'std::span<double>::span' requested here
      (*(std::span<double>**)ret) = new std::span<double>((const std::vector<double, std::allocator<double> >&)*(const std::vector<double, std::allocator<double> >*)args[0]);
                                        ^
0
1
2
3
```

Reproducer:
```Python
import ROOT

ROOT.gInterpreter.Declare("""
void calc_cumsum(std::size_t n, std::span<double> v)
{
    for (int i = 0; i < n; i += 1) {
        std::cout << v[i] << std::endl;
    }
}
""")

v = ROOT.std.vector["double"](list(range(4)))

ROOT.calc_cumsum(len(v), v)
```
Copy link
Member

@pcanal pcanal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Consider adding a test though.

Use this in one of the `test_operators` tests, which actually prints jit
errors.
Test corresponding to commit:

"[core] Avoid errors when using std::span backport from Python".
@guitargeek guitargeek requested a review from vepadulano as a code owner August 25, 2025 21:51
@guitargeek guitargeek merged commit 988affc into root-project:master Aug 26, 2025
18 of 25 checks passed
@guitargeek guitargeek deleted the span_backport branch August 26, 2025 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants