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.
diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h
index e4029b9..e26e063 100644
--- a/include/pybind11/buffer_info.h
+++ b/include/pybind11/buffer_info.h
@@ -36,7 +36,7 @@
     }
 
     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,
diff --git a/include/pybind11/common.h b/include/pybind11/common.h
index d9d9d51..6df39f8 100644
--- a/include/pybind11/common.h
+++ b/include/pybind11/common.h
@@ -690,11 +690,6 @@
     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)) { }
 
diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h
index cbf4c2f..44ea427 100644
--- a/include/pybind11/numpy.h
+++ b/include/pybind11/numpy.h
@@ -458,7 +458,7 @@
         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 @@
     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 @@
     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 @@
     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);
     }
diff --git a/tests/test_numpy_array.cpp b/tests/test_numpy_array.cpp
index 7252547..269f18b 100644
--- a/tests/test_numpy_array.cpp
+++ b/tests/test_numpy_array.cpp
@@ -267,4 +267,10 @@
     // 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 }); });
 });