Fix undefined memoryview format (#2223)

* Fix undefined memoryview format

* Add missing <algorithm> header

* Add workaround for py27 array compatibility

* Workaround py27 memoryview behavior

* Fix memoryview constructor from buffer_info

* Workaround PyMemoryView_FromMemory availability in py27

* Fix up memoryview tests

* Update memoryview test from buffer to check signedness

* Use static factory method to create memoryview

* Remove ndim arg from memoryview::frombuffer and add tests

* Allow ndim=0 memoryview and documentation fixup

* Use void* to align to frombuffer method signature

* Add const variants of frombuffer and frommemory

* Add memory view section in doc

* Fix docs

* Add test for null buffer

* Workaround py27 nullptr behavior in test

* Rename frombuffer to from_buffer
diff --git a/docs/advanced/pycpp/numpy.rst b/docs/advanced/pycpp/numpy.rst
index 3d9c90c..aef7abe 100644
--- a/docs/advanced/pycpp/numpy.rst
+++ b/docs/advanced/pycpp/numpy.rst
@@ -384,3 +384,45 @@
 
    py::array a = /* A NumPy array */;
    py::array b = a[py::make_tuple(0, py::ellipsis(), 0)];
+
+Memory view
+===========
+
+For a case when we simply want to provide a direct accessor to C/C++ buffer
+without a concrete class object, we can return a ``memoryview`` object. Suppose
+we wish to expose a ``memoryview`` for 2x4 uint8_t array, we can do the
+following:
+
+.. code-block:: cpp
+
+    const uint8_t buffer[] = {
+        0, 1, 2, 3,
+        4, 5, 6, 7
+    };
+    m.def("get_memoryview2d", []() {
+        return py::memoryview::from_buffer(
+            buffer,                                    // buffer pointer
+            { 2, 4 },                                  // shape (rows, cols)
+            { sizeof(uint8_t) * 4, sizeof(uint8_t) }   // strides in bytes
+        );
+    })
+
+This approach is meant for providing a ``memoryview`` for a C/C++ buffer not
+managed by Python. The user is responsible for managing the lifetime of the
+buffer. Using a ``memoryview`` created in this way after deleting the buffer in
+C++ side results in undefined behavior.
+
+We can also use ``memoryview::from_memory`` for a simple 1D contiguous buffer:
+
+.. code-block:: cpp
+
+    m.def("get_memoryview1d", []() {
+        return py::memoryview::from_memory(
+            buffer,               // buffer pointer
+            sizeof(uint8_t) * 8   // buffer size
+        );
+    })
+
+.. note::
+
+    ``memoryview::from_memory`` is not available in Python 2.