Adding documentation for value_error. Fixing various formatting issues. Removing redundant binding for C++ style methods. Adding bindings for iterator and slicing protocol. Extending examples.
diff --git a/docs/advanced.rst b/docs/advanced.rst
index e83ba27..837450e 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -779,6 +779,10 @@
 |                                      | accesses in ``__getitem__``, |
 |                                      | ``__setitem__``, etc.)       |
 +--------------------------------------+------------------------------+
+| :class:`pybind11::value_error`       | ``ValueError`` (used to      |
+|                                      | indicate wrong value passed  |
+|                                      | in ``container.remove(...)`` |
++--------------------------------------+------------------------------+
 | :class:`pybind11::error_already_set` | Indicates that the Python    |
 |                                      | exception flag has already   |
 |                                      | been initialized             |
@@ -1531,4 +1535,3 @@
 
 .. [#f4] http://www.sphinx-doc.org
 .. [#f5] http://github.com/pybind/pbtest
-
diff --git a/example/example17.cpp b/example/example17.cpp
index 8c30457..8370b5c 100644
--- a/example/example17.cpp
+++ b/example/example17.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example17.cpp -- Usade of stl_binders functions
+    example/example17.cpp -- Usage of stl_binders functions
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -11,17 +11,27 @@
 
 #include <pybind11/stl_binders.h>
 
-class A
-{
+
+class A {
 public:
 	A() = delete;
+	A(int v) :a(v) {}
+
+	int a;
 };
 
-void init_ex17(py::module &m)
-{
-	pybind11::class_<A>(m, "A");
 
-    py::vector_binder<int>(m, "VectorInt");
+std::ostream & operator<<(std::ostream &s, A const&v) {
+	s << "A{" << v.a << '}';
+	return s;
+}
 
-    py::vector_binder<A>(m, "VectorA");
+
+void init_ex17(py::module &m) {
+	pybind11::class_<A>(m, "A")
+		.def(pybind11::init<int>());
+
+	pybind11::vector_binder<int>(m, "VectorInt");
+
+	pybind11::vector_binder<A>(m, "VectorA");
 }
diff --git a/example/example17.py b/example/example17.py
index d41a325..52cda42 100644
--- a/example/example17.py
+++ b/example/example17.py
@@ -1,24 +1,31 @@
 #!/usr/bin/env python
 from __future__ import print_function
 
-from example import VectorInt, VectorA
+from example import VectorInt, VectorA, A
 
 v_int = VectorInt(2)
-print( v_int.size() )
+print(len(v_int))
 
-print( bool(v_int) )
+print(bool(v_int))
 
 v_int2 = VectorInt(2)
-print( v_int == v_int2 )
+print(v_int == v_int2)
 
 v_int2[1] = 1
-print( v_int != v_int2 )
+print(v_int != v_int2)
 
-v_int2.push_back(2)
-v_int2.push_back(3)
+v_int2.append(2)
+v_int2.append(3)
 v_int2.insert(0, 1)
 v_int2.insert(0, 2)
 v_int2.insert(0, 3)
 print(v_int2)
 
+v_int.append(99)
+v_int2[2:-2] = v_int
+print(v_int2)
+
 v_a = VectorA()
+v_a.append(A(1))
+v_a.append(A(2))
+print(v_a)
diff --git a/example/example17.ref b/example/example17.ref
index 249fbab..388e0f0 100644
--- a/example/example17.ref
+++ b/example/example17.ref
@@ -3,3 +3,9 @@
 True
 True
 VectorInt[3, 2, 1, 0, 1, 2, 3]
+VectorInt[3, 2, 0, 0, 99, 2, 3]
+A constructor
+A destructor
+A constructor
+A destructor
+VectorA[A{1}, A{2}]
\ No newline at end of file
diff --git a/include/pybind11/stl_binders.h b/include/pybind11/stl_binders.h
index a2af0ac..7b0047d 100644
--- a/include/pybind11/stl_binders.h
+++ b/include/pybind11/stl_binders.h
@@ -27,14 +27,14 @@
 
 
 template<typename T>
-constexpr auto has_equal_operator(int) -> decltype( std::declval<T>() == std::declval<T>(), bool()) { return true; }
+constexpr auto has_equal_operator(int) -> decltype(std::declval<T>() == std::declval<T>(), bool()) { return true; }
 template<typename T>
 constexpr bool has_equal_operator(...) { return false; }
 
 
 
 template<typename T>
-constexpr auto has_not_equal_operator(int) -> decltype( std::declval<T>() != std::declval<T>(), bool()) { return true; }
+constexpr auto has_not_equal_operator(int) -> decltype(std::declval<T>() != std::declval<T>(), bool()) { return true; }
 template<typename T>
 constexpr bool has_not_equal_operator(...) { return false; }
 
@@ -43,22 +43,20 @@
 namespace has_insertion_operator_implementation {
 enum class False {};
 struct any_type {
-    template<typename T> any_type( T const& );
+    template<typename T> any_type(T const&);
 };
-False operator<<( std::ostream const&, any_type const& );
+False operator<<(std::ostream const&, any_type const&);
 }
 template<typename T>
-constexpr bool has_insertion_operator()
-{
+constexpr bool has_insertion_operator() {
 	using namespace has_insertion_operator_implementation;
-	return std::is_same< decltype( std::declval<std::ostringstream&>() << std::declval<T>() ), std::ostream & >::value;
+	return std::is_same< decltype(std::declval<std::ostream&>() << std::declval<T>()), std::ostream & >::value;
 }
 #endif
 
 
 template <typename T, typename Allocator = std::allocator<T>, typename holder_type = std::unique_ptr< std::vector<T, Allocator> > >
-class vector_binder
-{
+class vector_binder {
 	using Vector = std::vector<T, Allocator>;
 	using SizeType = typename Vector::size_type;
 
@@ -72,16 +70,28 @@
 	// void maybe_constructible(Class_ &cl) {}
 
 	template<typename U = T, typename std::enable_if< std::is_default_constructible<U>{} >::type * = nullptr>
-	void maybe_default_constructible(Class_ &cl) {
+	void maybe_default_constructible() {
 		cl.def(pybind11::init<SizeType>());
 		cl.def("resize", (void (Vector::*)(SizeType count)) &Vector::resize, "changes the number of elements stored");
+
+		/// Slicing protocol
+		cl.def("__getitem__", [](Vector const &v, pybind11::slice slice) -> Vector * {
+				pybind11::ssize_t start, stop, step, slicelength;
+				if(!slice.compute(v.size(), &start, &stop, &step, &slicelength))
+					throw pybind11::error_already_set();
+				Vector *seq = new Vector(slicelength);
+				for (int i=0; i<slicelength; ++i) {
+					(*seq)[i] = v[start]; start += step;
+				}
+				return seq;
+			});
 	}
 	template<typename U = T, typename std::enable_if< !std::is_default_constructible<U>{} >::type * = nullptr>
-	void maybe_default_constructible(Class_ &) {}
+	void maybe_default_constructible() {}
 
 
 	template<typename U = T, typename std::enable_if< std::is_copy_constructible<U>{} >::type * = nullptr>
-	void maybe_copy_constructible(Class_ &cl) {
+	void maybe_copy_constructible() {
 		cl.def(pybind11::init< Vector const &>());
 	}
 	template<typename U = T, typename std::enable_if< !std::is_copy_constructible<U>{} >::type * = nullptr>
@@ -89,39 +99,41 @@
 
 
 	template<typename U = T, typename std::enable_if< has_equal_operator<U>(0) >::type * = nullptr>
-	void maybe_has_equal_operator(Class_ &cl) {
+	void maybe_has_equal_operator() {
 	    cl.def(pybind11::self == pybind11::self);
 	    cl.def(pybind11::self != pybind11::self);
 
 		cl.def("count", [](Vector const &v, T const & value) { return std::count(v.begin(), v.end(), value); }, "counts the elements that are equal to value");
 
-		cl.def("remove", [](Vector &v, const T&t) {
+		cl.def("remove", [](Vector &v, T const &t) {
 				auto p = std::find(v.begin(), v.end(), t);
-				if( p != v.end() ) v.erase(p);
+				if(p != v.end()) v.erase(p);
 				else throw pybind11::value_error();
 			}, "Remove the first item from the list whose value is x. It is an error if there is no such item.");
+
+		cl.def("__contains__", [](Vector const &v, T const &t) { return std::find(v.begin(), v.end(), t) != v.end(); }, "return true if item in the container");
 	}
 	template<typename U = T, typename std::enable_if< !has_equal_operator<U>(0) >::type * = nullptr>
-	void maybe_has_equal_operator(Class_ &) {}
+	void maybe_has_equal_operator() {}
 
 
 	template<typename U = T, typename std::enable_if< has_not_equal_operator<U>(0) >::type * = nullptr>
-	void maybe_has_not_equal_operator(Class_ &cl) {
+	void maybe_has_not_equal_operator() {
 	    cl.def(pybind11::self != pybind11::self);
 	}
 	template<typename U = T, typename std::enable_if< !has_not_equal_operator<U>(0) >::type * = nullptr>
-	void maybe_has_not_equal_operator(Class_ &) {}
+	void maybe_has_not_equal_operator() {}
 
 
 	#ifdef INSERTION_OPERATOR_IMPLEMENTATION
 	template<typename U = T, typename std::enable_if< has_insertion_operator<U>() >::type * = nullptr>
-	void maybe_has_insertion_operator(Class_ &cl, std::string name) {
+	void maybe_has_insertion_operator(char const *name) {
 		cl.def("__repr__", [name](typename vector_binder<T>::Vector &v) {
 				std::ostringstream s;
 				s << name << '[';
 				for(uint i=0; i<v.size(); ++i) {
 					s << v[i];
-					if( i != v.size() -1 ) s << ", ";
+					if(i != v.size()-1) s << ", ";
 				}
 				s << ']';
 				return s.str();
@@ -129,64 +141,65 @@
 
 	}
 	template<typename U = T, typename std::enable_if< !has_insertion_operator<U>() >::type * = nullptr>
-	void maybe_has_insertion_operator(Class_ &, char const *) {}
+	void maybe_has_insertion_operator(char const *) {}
 	#endif
 
 
 
 public:
-	vector_binder(pybind11::module &m, char const *name) {
-		Class_ cl(m, name);
+	Class_ cl;
 
+	vector_binder(pybind11::module &m, char const *name, char const *doc=nullptr) : cl(m, name, doc) {
 		cl.def(pybind11::init<>());
 
 		//maybe_constructible(cl);
-		maybe_default_constructible(cl);
-		maybe_copy_constructible(cl);
+		maybe_default_constructible();
+		maybe_copy_constructible();
 
 		// Element access
 		cl.def("front", [](Vector &v) {
-				if( v.size() ) return v.front();
+				if(v.size()) return v.front();
 				else throw pybind11::index_error();
 			}, "access the first element");
 		cl.def("back", [](Vector &v) {
-				if( v.size() ) return v.back();
+				if(v.size()) return v.back();
 				else throw pybind11::index_error();
 			}, "access the last element ");
 		// Not needed, the operator[] is already providing bounds checking cl.def("at", (T& (Vector::*)(SizeType i)) &Vector::at, "access specified element with bounds checking");
 
 
-		// Capacity
-		cl.def("empty",         &Vector::empty,         "checks whether the container is empty");
-		cl.def("size",          &Vector::size,          "returns the number of elements");
+		// Capacity, C++ style
 		cl.def("max_size",      &Vector::max_size,      "returns the maximum possible number of elements");
 		cl.def("reserve",       &Vector::reserve,       "reserves storage");
 		cl.def("capacity",      &Vector::capacity,      "returns the number of elements that can be held in currently allocated storage");
 		cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
 
 		// Modifiers, C++ style
-		cl.def("clear",                                      &Vector::clear, "clears the contents");
-		cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
-		cl.def("pop_back",                                &Vector::pop_back, "removes the last element");
-		cl.def("swap",                                        &Vector::swap, "swaps the contents");
-
+		cl.def("clear", &Vector::clear, "clears the contents");
+		cl.def("swap",   &Vector::swap, "swaps the contents");
 
 		// Modifiers, Python style
 		cl.def("append", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
 		cl.def("insert", [](Vector &v, SizeType i, const T&t) {v.insert(v.begin()+i, t);}, "insert an item at a given position");
 		cl.def("pop", [](Vector &v) {
-				if( v.size() ) {
+				if(v.size()) {
 					T t = v.back();
 					v.pop_back();
 					return t;
 				}
 				else throw pybind11::index_error();
-			}, "insert an item at a given position");
+			}, "remove and return last item");
 
+		cl.def("pop", [](Vector &v, SizeType i) {
+				if(i >= v.size()) throw pybind11::index_error();
+				T t = v[i];
+				v.erase(v.begin() + i);
+				return t;
+			}, "remove and return item at index");
 
 		cl.def("erase", [](Vector &v, SizeType i) {
-				if( i >= v.size() ) throw pybind11::index_error();
-				v.erase( v.begin() + i );
+				if(i >= v.size()) throw pybind11::index_error();
+				v.erase(v.begin() + i);
 			}, "erases element at index");
 
 
@@ -198,25 +211,46 @@
 		#endif
 
 		cl.def("__getitem__", [](Vector const &v, SizeType i) {
-				if( i >= v.size() ) throw pybind11::index_error();
+				if(i >= v.size()) throw pybind11::index_error();
 				return v[i];
 			});
 
 		cl.def("__setitem__", [](Vector &v, SizeType i, T const & t) {
-				if( i >= v.size() ) throw pybind11::index_error();
+				if(i >= v.size()) throw pybind11::index_error();
 				v[i] = t;
 		});
 
 		cl.def("__len__", &Vector::size);
 
+		cl.def("__iter__", [](Vector &v) { return pybind11::make_iterator(v.begin(), v.end()); },
+			   pybind11::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */);
+
+		/// Slicing protocol
+		cl.def("__setitem__", [](Vector &v, pybind11::slice slice,  Vector const &value) {
+				pybind11::ssize_t start, stop, step, slicelength;
+				if(!slice.compute(v.size(), &start, &stop, &step, &slicelength))
+					throw pybind11::error_already_set();
+				if((size_t) slicelength != value.size())
+					throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
+				for(int i=0; i<slicelength; ++i) {
+					v[start] = value[i]; start += step;
+				}
+			});
+
 		// Comparisons
-		maybe_has_equal_operator(cl);
-		maybe_has_not_equal_operator(cl);
+		maybe_has_equal_operator();
+		maybe_has_not_equal_operator();
 
 		// Printing
 		#ifdef INSERTION_OPERATOR_IMPLEMENTATION
-		maybe_has_insertion_operator(cl, name);
+		maybe_has_insertion_operator(name);
 		#endif
+
+		// C++ style functions deprecated, leaving it here as an example
+		//cl.def("empty",         &Vector::empty,         "checks whether the container is empty");
+		//cl.def("size",          &Vector::size,          "returns the number of elements");
+		//cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
+		//cl.def("pop_back",                                &Vector::pop_back, "removes the last element");
 	}
 };