mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-31 07:10:30 +00:00
Fix ambiguous initialize_list arguments
This removes the convert-from-arithemtic-scalar constructor of any_container as it can result in ambiguous calls, as in: py::array_t<float>({ 1, 2 }) which could be intepreted as either of: py::array_t<float>(py::array_t<float>(1, 2)) py::array_t<float>(py::detail::any_container({ 1, 2 })) Removing the convert-from-arithmetic constructor reduces the number of implicit conversions, avoiding the ambiguity for array and array_t. This also re-adds the array/array_t constructors taking a scalar argument for backwards compatibility.
This commit is contained in:
parent
2761f78f11
commit
51d18aa252
@ -36,7 +36,7 @@ struct buffer_info {
|
||||
}
|
||||
|
||||
buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size)
|
||||
: buffer_info(ptr, itemsize, format, 1, size, itemsize) { }
|
||||
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { }
|
||||
|
||||
explicit buffer_info(Py_buffer *view, bool ownview = true)
|
||||
: buffer_info(view->buf, (size_t) view->itemsize, view->format, (size_t) view->ndim,
|
||||
|
@ -690,11 +690,6 @@ public:
|
||||
template <typename TIn, typename = enable_if_t<std::is_convertible<TIn, T>::value>>
|
||||
any_container(const std::initializer_list<TIn> &c) : any_container(c.begin(), c.end()) { }
|
||||
|
||||
// Implicit conversion constructor from any arithmetic type (only participates if T is also
|
||||
// arithmetic).
|
||||
template <typename TIn, typename = enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<TIn>::value>>
|
||||
any_container(TIn singleton) : v(1, static_cast<T>(singleton)) { }
|
||||
|
||||
// Avoid copying if given an rvalue vector of the correct type.
|
||||
any_container(std::vector<T> &&v) : v(std::move(v)) { }
|
||||
|
||||
|
@ -458,7 +458,7 @@ public:
|
||||
forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
|
||||
};
|
||||
|
||||
array() : array(0, static_cast<const double *>(nullptr)) {}
|
||||
array() : array({{0}}, static_cast<const double *>(nullptr)) {}
|
||||
|
||||
using ShapeContainer = detail::any_container<Py_intptr_t>;
|
||||
using StridesContainer = detail::any_container<Py_intptr_t>;
|
||||
@ -504,12 +504,9 @@ public:
|
||||
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr = nullptr, handle base = handle())
|
||||
: array(dt, std::move(shape), {}, ptr, base) { }
|
||||
|
||||
// This constructor is only needed to avoid ambiguity with the deprecated (handle, bool)
|
||||
// constructor that comes from PYBIND11_OBJECT_CVT; once that is gone, the above constructor can
|
||||
// handle it (because ShapeContainer is implicitly constructible from arithmetic types)
|
||||
template <typename T, typename = detail::enable_if_t<std::is_arithmetic<T>::value && !std::is_same<bool, T>::value>>
|
||||
array(const pybind11::dtype &dt, T count)
|
||||
: array(dt, count, nullptr) { }
|
||||
template <typename T, typename = detail::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
|
||||
array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle())
|
||||
: array(dt, {{count}}, ptr, base) { }
|
||||
|
||||
template <typename T>
|
||||
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle())
|
||||
@ -519,6 +516,9 @@ public:
|
||||
array(ShapeContainer shape, const T *ptr, handle base = handle())
|
||||
: array(std::move(shape), {}, ptr, base) { }
|
||||
|
||||
template <typename T>
|
||||
explicit array(size_t count, const T *ptr, handle base = handle()) : array({count}, {}, ptr, base) { }
|
||||
|
||||
explicit array(const buffer_info &info)
|
||||
: array(pybind11::dtype(info), info.shape, info.strides, info.ptr) { }
|
||||
|
||||
@ -743,6 +743,9 @@ public:
|
||||
explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle())
|
||||
: array(std::move(shape), ptr, base) { }
|
||||
|
||||
explicit array_t(size_t count, const T *ptr = nullptr, handle base = handle())
|
||||
: array({count}, {}, ptr, base) { }
|
||||
|
||||
constexpr size_t itemsize() const {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
@ -267,4 +267,10 @@ test_initializer numpy_array([](py::module &m) {
|
||||
// Issue #785: Uninformative "Unknown internal error" exception when constructing array from empty object:
|
||||
sm.def("array_fail_test", []() { return py::array(py::object()); });
|
||||
sm.def("array_t_fail_test", []() { return py::array_t<double>(py::object()); });
|
||||
|
||||
// Issue (unnumbered; reported in #788): regression: initializer lists can be ambiguous
|
||||
sm.def("array_initializer_list", []() { return py::array_t<float>(1); }); // { 1 } also works, but clang warns about it
|
||||
sm.def("array_initializer_list", []() { return py::array_t<float>({ 1, 2 }); });
|
||||
sm.def("array_initializer_list", []() { return py::array_t<float>({ 1, 2, 3 }); });
|
||||
sm.def("array_initializer_list", []() { return py::array_t<float>({ 1, 2, 3, 4 }); });
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user