From 201796d94f29a6ab25628505c44c036d2dc43cad Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 12 Apr 2017 18:35:46 -0400 Subject: [PATCH] Make any_container implicitly constructible from arithmetic values This further reduces the constructors required in buffer_info/numpy by removing the need for the constructors that take a single size_t and just forward it on via an initializer_list to the container-accepting constructor. Unfortunately, in `array` one of the constructors runs into an ambiguity problem with the deprecated `array(handle, bool)` constructor (because both the bool constructor and the any_container constructor involve an implicit conversion, so neither has precedence), so a forwarding constructor is kept there (until the deprecated constructor is eventually removed). --- include/pybind11/buffer_info.h | 2 +- include/pybind11/common.h | 8 +++++++- include/pybind11/numpy.h | 18 +++++++----------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index ead972fb7..54451ee3d 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -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_in = true) : buffer_info(view->buf, (size_t) view->itemsize, view->format, (size_t) view->ndim, diff --git a/include/pybind11/common.h b/include/pybind11/common.h index bf032bbab..e08c56b55 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -660,7 +660,8 @@ static constexpr auto const_ = std::true_type{}; NAMESPACE_BEGIN(detail) // Adaptor for converting arbitrary container arguments into a vector; implicitly convertible from -// any standard container (or C-style array) supporting std::begin/std::end. +// any standard container (or C-style array) supporting std::begin/std::end, any singleton +// arithmetic type (if T is arithmetic), or explicitly constructible from an iterator pair. template class any_container { std::vector v; @@ -680,6 +681,11 @@ public: template ::value>> any_container(const std::initializer_list &c) : any_container(c.begin(), c.end()) { } + // Implicit conversion constructor from any arithmetic type (only participates if T is also + // arithmetic). + template ::value && std::is_arithmetic::value>> + any_container(TIn singleton) : v(1, static_cast(singleton)) { } + // Avoid copying if given an rvalue vector of the correct type. any_container(std::vector &&v) : v(std::move(v)) { } diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 5d44539f6..b32c38874 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -463,7 +463,7 @@ public: const void *ptr = nullptr, handle base = handle()) { if (strides->empty()) - strides = default_strides(*shape, dt.itemsize()); + *strides = default_strides(*shape, dt.itemsize()); auto ndim = shape->size(); if (ndim != strides->size()) @@ -499,9 +499,12 @@ public: array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr = nullptr, handle base = handle()) : array(dt, std::move(shape), {}, ptr, base) { } - array(const pybind11::dtype &dt, size_t count, const void *ptr = nullptr, - handle base = handle()) - : array(dt, ShapeContainer{{ count }}, 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 ::value && !std::is_same::value>> + array(const pybind11::dtype &dt, T count) + : array(dt, count, nullptr) { } template array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle()) @@ -511,10 +514,6 @@ public: array(ShapeContainer shape, const T *ptr, handle base = handle()) : array(std::move(shape), {}, ptr, base) { } - template - 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) { } @@ -739,9 +738,6 @@ 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); }