support unordered set/map data structures (fixes #100)
diff --git a/docs/basics.rst b/docs/basics.rst
index 7c2b4ee..53a325e 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -222,45 +222,49 @@
 an additional extension header to be included). To pass other data structures
 as arguments and return values, refer to the section on binding :ref:`classes`.
 
-+------------------------+--------------------------+-----------------------+
-|  Data type             |  Description             | Header file           |
-+========================+==========================+=======================+
-| int8_t, uint8_t        | 8-bit integers           | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| int16_t, uint16_t      | 16-bit integers          | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| int32_t, uint32_t      | 32-bit integers          | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| int64_t, uint64_t      | 64-bit integers          | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| ssize_t, size_t        | Platform-dependent size  | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| float, double          | Floating point types     | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| bool                   | Two-state Boolean type   | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| char                   | Character literal        | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| const char *           | UTF-8 string literal     | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| std::string            | STL dynamic UTF-8 string | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| std::pair<T1, T2>      | Pair of two custom types | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| std::tuple<....>       | Arbitrary tuple of types | pybind11/pybind11.h   |
-+------------------------+--------------------------+-----------------------+
-| std::complex<T>        | Complex numbers          | pybind11/complex.h    |
-+------------------------+--------------------------+-----------------------+
-| std::array<T, Size>    | STL static array         | pybind11/stl.h        |
-+------------------------+--------------------------+-----------------------+
-| std::vector<T>         | STL dynamic array        | pybind11/stl.h        |
-+------------------------+--------------------------+-----------------------+
-| std::map<T1, T2>       | STL ordered map          | pybind11/stl.h        |
-+------------------------+--------------------------+-----------------------+
-| std::set<T>            | STL ordered set          | pybind11/stl.h        |
-+------------------------+--------------------------+-----------------------+
-| std::function<...>     | STL polymorphic function | pybind11/functional.h |
-+------------------------+--------------------------+-----------------------+
++----------------------------+--------------------------+-----------------------+
+|  Data type                 |  Description             | Header file           |
++============================+==========================+=======================+
+| int8_t, uint8_t            | 8-bit integers           | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| int16_t, uint16_t          | 16-bit integers          | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| int32_t, uint32_t          | 32-bit integers          | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| int64_t, uint64_t          | 64-bit integers          | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| ssize_t, size_t            | Platform-dependent size  | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| float, double              | Floating point types     | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| bool                       | Two-state Boolean type   | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| char                       | Character literal        | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| const char *               | UTF-8 string literal     | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| std::string                | STL dynamic UTF-8 string | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| std::pair<T1, T2>          | Pair of two custom types | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| std::tuple<....>           | Arbitrary tuple of types | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
+| std::complex<T>            | Complex numbers          | pybind11/complex.h    |
++----------------------------+--------------------------+-----------------------+
+| std::array<T, Size>        | STL static array         | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::vector<T>             | STL dynamic array        | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::map<T1, T2>           | STL ordered map          | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::unordered_map<T1, T2> | STL unordered map        | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::set<T>                | STL ordered set          | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::unordered_set<T>      | STL unordered set        | pybind11/stl.h        |
++----------------------------+--------------------------+-----------------------+
+| std::function<...>         | STL polymorphic function | pybind11/functional.h |
++----------------------------+--------------------------+-----------------------+
 
 
 .. [#f1] In practice, implementation and binding code will generally be located
diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h
index dcb96e0..1ee2cc4 100644
--- a/include/pybind11/stl.h
+++ b/include/pybind11/stl.h
@@ -10,8 +10,10 @@
 #pragma once
 
 #include "pybind11.h"
-#include <map>
 #include <set>
+#include <unordered_set>
+#include <map>
+#include <unordered_map>
 #include <iostream>
 
 #if defined(_MSC_VER)
@@ -22,77 +24,10 @@
 NAMESPACE_BEGIN(pybind11)
 NAMESPACE_BEGIN(detail)
 
-template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> {
-    typedef std::vector<Type, Alloc> vector_type;
-    typedef type_caster<Type> value_conv;
-public:
-    bool load(handle src, bool convert) {
-        list l(src, true);
-        if (!l.check())
-            return false;
-        value.reserve(l.size());
-        value.clear();
-        value_conv conv;
-        for (auto it : l) {
-            if (!conv.load(it, convert))
-                return false;
-            value.push_back((Type) conv);
-        }
-        return true;
-    }
-
-    static handle cast(const vector_type &src, return_value_policy policy, handle parent) {
-        list l(src.size());
-        size_t index = 0;
-        for (auto const &value: src) {
-            object value_ = object(value_conv::cast(value, policy, parent), false);
-            if (!value_)
-                return handle();
-            PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
-        }
-        return l.release();
-    }
-    PYBIND11_TYPE_CASTER(vector_type, _("list<") + value_conv::name() + _(">"));
-};
-
-template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> {
-    typedef std::array<Type, Size> array_type;
-    typedef type_caster<Type> value_conv;
-public:
-    bool load(handle src, bool convert) {
-        list l(src, true);
-        if (!l.check())
-            return false;
-        if (l.size() != Size)
-            return false;
-        value_conv conv;
-        size_t ctr = 0;
-        for (auto it : l) {
-            if (!conv.load(it, convert))
-                return false;
-            value[ctr++] = (Type) conv;
-        }
-        return true;
-    }
-
-    static handle cast(const array_type &src, return_value_policy policy, handle parent) {
-        list l(Size);
-        size_t index = 0;
-        for (auto const &value: src) {
-            object value_ = object(value_conv::cast(value, policy, parent), false);
-            if (!value_)
-                return handle();
-            PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
-        }
-        return l.release();
-    }
-    PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]"));
-};
-
-template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> {
-    typedef std::set<Key, Compare, Alloc> type;
+template <typename Type, typename Key> struct set_caster {
+    typedef Type type;
     typedef type_caster<Key> key_conv;
-public:
+
     bool load(handle src, bool convert) {
         pybind11::set s(src, true);
         if (!s.check())
@@ -116,12 +51,12 @@
         }
         return s.release();
     }
+
     PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
 };
 
-template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> {
-public:
-    typedef std::map<Key, Value, Compare, Alloc>  type;
+template <typename Type, typename Key, typename Value> struct map_caster {
+    typedef Type type;
     typedef type_caster<Key>   key_conv;
     typedef type_caster<Value> value_conv;
 
@@ -156,6 +91,85 @@
     PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
 };
 
+template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> {
+    typedef std::vector<Type, Alloc> vector_type;
+    typedef type_caster<Type> value_conv;
+
+    bool load(handle src, bool convert) {
+        list l(src, true);
+        if (!l.check())
+            return false;
+        value.reserve(l.size());
+        value.clear();
+        value_conv conv;
+        for (auto it : l) {
+            if (!conv.load(it, convert))
+                return false;
+            value.push_back((Type) conv);
+        }
+        return true;
+    }
+
+    static handle cast(const vector_type &src, return_value_policy policy, handle parent) {
+        list l(src.size());
+        size_t index = 0;
+        for (auto const &value: src) {
+            object value_ = object(value_conv::cast(value, policy, parent), false);
+            if (!value_)
+                return handle();
+            PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
+        }
+        return l.release();
+    }
+    PYBIND11_TYPE_CASTER(vector_type, _("list<") + value_conv::name() + _(">"));
+};
+
+template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> {
+    typedef std::array<Type, Size> array_type;
+    typedef type_caster<Type> value_conv;
+
+    bool load(handle src, bool convert) {
+        list l(src, true);
+        if (!l.check())
+            return false;
+        if (l.size() != Size)
+            return false;
+        value_conv conv;
+        size_t ctr = 0;
+        for (auto it : l) {
+            if (!conv.load(it, convert))
+                return false;
+            value[ctr++] = (Type) conv;
+        }
+        return true;
+    }
+
+    static handle cast(const array_type &src, return_value_policy policy, handle parent) {
+        list l(Size);
+        size_t index = 0;
+        for (auto const &value: src) {
+            object value_ = object(value_conv::cast(value, policy, parent), false);
+            if (!value_)
+                return handle();
+            PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
+        }
+        return l.release();
+    }
+    PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]"));
+};
+
+template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
+  : set_caster<std::set<Key, Compare, Alloc>, Key> { };
+
+template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
+  : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
+
+template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
+  : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
+
+template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
+  : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
+
 NAMESPACE_END(detail)
 
 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {