Access C++ hash functions from Python and vice versa (#1034)

There are two separate additions:

1. `py::hash(obj)` is equivalent to the Python `hash(obj)`.
2. `.def(hash(py::self))` registers the hash function defined by
   `std::hash<T>` as the Python hash function.
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 478b7d7..7f898fe 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -243,6 +243,11 @@
 * Fixed implicit conversion of `py::enum_` to integer types on Python 2.7.
   `#821 <https://github.com/pybind/pybind11/pull/821>`_.
 
+* Added ``py::hash`` to fetch the hash value of Python objects, and
+  ``.def(hash(py::self))`` to provide the C++ ``std::hash`` as the Python
+  ``__hash__`` method.
+  `#1034 <https://github.com/pybind/pybind11/pull/1034>`_.
+
 * Fixed ``__truediv__`` on Python 2 and ``__itruediv__`` on Python 3.
   `#867 <https://github.com/pybind/pybind11/pull/867>`_.
 
diff --git a/include/pybind11/operators.h b/include/pybind11/operators.h
index 11ea248..b3dd62c 100644
--- a/include/pybind11/operators.h
+++ b/include/pybind11/operators.h
@@ -28,7 +28,7 @@
     op_int, op_long, op_float, op_str, op_cmp, op_gt, op_ge, op_lt, op_le,
     op_eq, op_ne, op_iadd, op_isub, op_imul, op_idiv, op_imod, op_ilshift,
     op_irshift, op_iand, op_ixor, op_ior, op_complex, op_bool, op_nonzero,
-    op_repr, op_truediv, op_itruediv
+    op_repr, op_truediv, op_itruediv, op_hash
 };
 
 enum op_type : int {
@@ -148,6 +148,7 @@
 PYBIND11_UNARY_OPERATOR(neg,        operator-,    -l)
 PYBIND11_UNARY_OPERATOR(pos,        operator+,    +l)
 PYBIND11_UNARY_OPERATOR(abs,        abs,          std::abs(l))
+PYBIND11_UNARY_OPERATOR(hash,       hash,         std::hash<L>()(l))
 PYBIND11_UNARY_OPERATOR(invert,     operator~,    (~l))
 PYBIND11_UNARY_OPERATOR(bool,       operator!,    !!l)
 PYBIND11_UNARY_OPERATOR(int,        int_,         (int) l)
diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h
index 9e18a01..92316c3 100644
--- a/include/pybind11/pytypes.h
+++ b/include/pybind11/pytypes.h
@@ -390,6 +390,13 @@
 inline void setattr(handle obj, const char *name, handle value) {
     if (PyObject_SetAttrString(obj.ptr(), name, value.ptr()) != 0) { throw error_already_set(); }
 }
+
+inline ssize_t hash(handle obj) {
+    auto h = PyObject_Hash(obj.ptr());
+    if (h == -1) { throw error_already_set(); }
+    return h;
+}
+
 /// @} python_builtins
 
 NAMESPACE_BEGIN(detail)
diff --git a/tests/test_operator_overloading.cpp b/tests/test_operator_overloading.cpp
index d4d35f0..4ad34d1 100644
--- a/tests/test_operator_overloading.cpp
+++ b/tests/test_operator_overloading.cpp
@@ -10,6 +10,7 @@
 #include "pybind11_tests.h"
 #include "constructor_stats.h"
 #include <pybind11/operators.h>
+#include <functional>
 
 class Vector2 {
 public:
@@ -53,6 +54,14 @@
 int operator+(const C2 &, const C1 &) { return 21; }
 int operator+(const C1 &, const C2 &) { return 12; }
 
+namespace std {
+    template<>
+    struct hash<Vector2> {
+        // Not a good hash function, but easy to test
+        size_t operator()(const Vector2 &) { return 4; }
+    };
+}
+
 TEST_SUBMODULE(operators, m) {
 
     // test_operator_overloading
@@ -77,6 +86,7 @@
         .def(float() * py::self)
         .def(float() / py::self)
         .def("__str__", &Vector2::toString)
+        .def(hash(py::self))
         ;
 
     m.attr("Vector") = m.attr("Vector2");
diff --git a/tests/test_operator_overloading.py b/tests/test_operator_overloading.py
index 845cedd..0d80e5e 100644
--- a/tests/test_operator_overloading.py
+++ b/tests/test_operator_overloading.py
@@ -35,6 +35,8 @@
     v2 /= v1
     assert str(v2) == "[2.000000, 8.000000]"
 
+    assert hash(v1) == 4
+
     cstats = ConstructorStats.get(m.Vector2)
     assert cstats.alive() == 2
     del v1
diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp
index edc1e99..4742236 100644
--- a/tests/test_pytypes.cpp
+++ b/tests/test_pytypes.cpp
@@ -261,4 +261,6 @@
     });
 
     m.def("print_failure", []() { py::print(42, UnregisteredType()); });
+
+    m.def("hash_function", [](py::object obj) { return py::hash(obj); });
 }
diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py
index b8dad84..2487cf6 100644
--- a/tests/test_pytypes.py
+++ b/tests/test_pytypes.py
@@ -220,3 +220,19 @@
         if debug_enabled else
         "arguments to Python object (compile in debug mode for details)"
     )
+
+
+def test_hash():
+    class Hashable(object):
+        def __init__(self, value):
+            self.value = value
+
+        def __hash__(self):
+            return self.value
+
+    class Unhashable(object):
+        __hash__ = None
+
+    assert m.hash_function(Hashable(42)) == 42
+    with pytest.raises(TypeError):
+        m.hash_function(Unhashable())