Skip to content

Commit 2f2b803

Browse files
committed
Implemented actual buffer_info constructor as private delegate constructor taking rvalue reference, solving the evaluation order move problem
1 parent 09b1f95 commit 2f2b803

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

include/pybind11/buffer_info.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,14 @@ struct buffer_info {
2727

2828
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
2929
detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in)
30-
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
31-
shape(std::move(shape_in)), strides(std::move(strides_in)) {
32-
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
33-
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
34-
for (size_t i = 0; i < (size_t) ndim; ++i)
35-
size *= shape[i];
36-
}
30+
: buffer_info(private_ctr_tag(), ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in)) { }
3731

3832
template <typename T>
3933
buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in)
40-
// Brace-initialization of the base class ensures left-to-right evaluation order of parameters (i.e. getting ndim before moving the shape container)
41-
: buffer_info{ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in)} { }
34+
: buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in)) { }
4235

4336
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size)
44-
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { }
37+
: buffer_info(private_ctr_tag(), ptr, itemsize, format, 1, {size}, {itemsize}) { }
4538

4639
template <typename T>
4740
buffer_info(T *ptr, ssize_t size)
@@ -79,6 +72,18 @@ struct buffer_info {
7972
}
8073

8174
private:
75+
struct private_ctr_tag { explicit private_ctr_tag() = default; };
76+
77+
buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
78+
detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in)
79+
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
80+
shape(std::move(shape_in)), strides(std::move(strides_in)) {
81+
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
82+
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
83+
for (size_t i = 0; i < (size_t) ndim; ++i)
84+
size *= shape[i];
85+
}
86+
8287
Py_buffer *view = nullptr;
8388
bool ownview = false;
8489
};

0 commit comments

Comments
 (0)