diff --git a/libwccl/values/bool.h b/libwccl/values/bool.h
index e0e05c3bf3f556c669b4d62e8813e83022c29d74..fd8a92f527e6bfb80fa3f727bd3efdde9f12a600 100644
--- a/libwccl/values/bool.h
+++ b/libwccl/values/bool.h
@@ -10,12 +10,14 @@ class Bool : public Value
 public:
 	WCCL_VALUE_PREAMBLE
 
+	typedef bool value_type;
+
 	explicit Bool(bool v = false)
 		: val_(v)
 	{
 	}
 
-	bool get_value() const {
+	const bool& get_value() const {
 		return val_;
 	}
 
diff --git a/libwccl/values/position.h b/libwccl/values/position.h
index 4b5eadc37ddd500f1c363a52d10820c605ca8761..747beda772a203f7d7cddcceca5edf782db5be6d 100644
--- a/libwccl/values/position.h
+++ b/libwccl/values/position.h
@@ -19,11 +19,13 @@ public:
 	{
 	}
 
+	typedef int value_type;
+
 	static const int Nowhere = boost::integer_traits<int>::const_min;
 	static const int Begin = boost::integer_traits<int>::const_min + 1;
 	static const int End = boost::integer_traits<int>::const_max;
 
-	int get_value() const {
+	const int& get_value() const {
 		return val_;
 	}
 
diff --git a/libwccl/values/strset.h b/libwccl/values/strset.h
index 49dfa5da688b126b7a3693ffbc45a46c221159ca..911a28d76b2f2b4e9e24631bd0a578d5602620f3 100644
--- a/libwccl/values/strset.h
+++ b/libwccl/values/strset.h
@@ -14,6 +14,8 @@ public:
 
 	typedef boost::unordered_set<UnicodeString> set_t;
 
+	typedef set_t value_type;
+
 	StrSet()
 		: set_()
 	{
diff --git a/libwccl/values/tset.h b/libwccl/values/tset.h
index 693006648f836870ee8866a7552cac4852f7f91a..0378628128aae708f119a46790c0a8c4de790e48 100644
--- a/libwccl/values/tset.h
+++ b/libwccl/values/tset.h
@@ -11,6 +11,8 @@ class TSet : public Value
 public:
 	WCCL_VALUE_PREAMBLE;
 
+	typedef Corpus2::Tag value_type;
+
 	TSet()
 		: tag_()
 	{
diff --git a/libwccl/variables.cpp b/libwccl/variables.cpp
index 419c44e210c71441339ca54012602a56a11a9b87..6f51e065595534571b3d9f35548245fa0ed177a8 100644
--- a/libwccl/variables.cpp
+++ b/libwccl/variables.cpp
@@ -21,7 +21,20 @@ struct delhelper
 		r = v.del<T>(s) || r;
 	}
 };
+} /* end anon ns */
+
+bool Variables::del_any(const std::string &s)
+{
+	bool rv = false;
+	typedef boost::mpl::pop_front< types >::type concrete;
+	// call delhelper::operator()<T> once for each of the allowed
+	// Value subtypes (but not for Value itself).
+	boost::mpl::for_each<concrete, boost::mpl::always<boost::mpl::_1> >(
+		delhelper(*this, s, rv));
+	return rv;
+}
 
+namespace {
 struct puthelper
 {
 	Variables& v;
@@ -41,29 +54,72 @@ struct puthelper
 		}
 	}
 };
-
 } /* end anon ns */
 
-bool Variables::del_any(const std::string &s)
+void Variables::put_any(const std::string &s, const boost::shared_ptr<Value> &v)
 {
 	bool rv = false;
 	typedef boost::mpl::pop_front< types >::type concrete;
-	// call delhelper::operator()<T> once for each of the allowed
+	// call puthelper::operator()<T> once for each of the allowed
 	// Value subtypes (but not for Value itself).
 	boost::mpl::for_each<concrete, boost::mpl::always<boost::mpl::_1> >(
-		delhelper(*this, s, rv));
-	return rv;
+		puthelper(*this, s, rv, v));
+	if (!rv) throw VariableTypeMismatch(s);
 }
 
-void Variables::put_any(const std::string &s, const boost::shared_ptr<Value> &v)
+namespace {
+struct resethelper
+{
+	const Variables& v;
+	resethelper(Variables& v): v(v) {}
+
+	template<typename T>
+	void operator()(const boost::mpl::always<T>&) {
+		typedef std::pair< std::string, boost::shared_ptr<T> > v_t;
+		foreach (const v_t& a, v.get_all<T>()) {
+			*a.second = T();
+		}
+	}
+};
+} /* end anon ns */
+
+
+void Variables::reset_values()
 {
-	bool rv = false;
 	typedef boost::mpl::pop_front< types >::type concrete;
-	// call puthelper::operator()<T> once for each of the allowed
-	// Value subtypes (but not for Value itself).
 	boost::mpl::for_each<concrete, boost::mpl::always<boost::mpl::_1> >(
-		puthelper(*this, s, rv, v));
-	if (!rv) throw VariableTypeMismatch(s);
+		resethelper(*this));
+}
+
+namespace {
+struct clonehelper
+{
+	const Variables& vfrom;
+	Variables::AccessHelper vto;
+	clonehelper(const Variables& vfrom, Variables::AccessHelper vto)
+		: vfrom(vfrom), vto(vto) {}
+
+	template<typename T>
+	void operator()(const boost::mpl::always<T>&) {
+		vto.access<T>() = vfrom.get_all<T>();
+		typedef typename detail::Vmap<T>::map_t::value_type value_type;
+		foreach (const value_type& a, vto.access<T>()) {
+			vto.vars.put(a.first, *a.second);
+		}
+	}
+};
+template<> inline
+void clonehelper::operator()(const boost::mpl::always<Value>&) {
+	vto.access<Value>() = vfrom.get_all<Value>();
+}
+} /* end anon ns */
+
+Variables* Variables::clone() const
+{
+	Variables* copy = new Variables;
+	boost::mpl::for_each<types, boost::mpl::always<boost::mpl::_1> >(
+		clonehelper(*this, Variables::AccessHelper(*copy)));
+	return copy;
 }
 
 } /* end ns Wccl */
diff --git a/libwccl/variables.h b/libwccl/variables.h
index c0dcab79cda4de1b6f3643e38ebd2a1f276918e1..35a99d31cc1642de729d8a4dc78c1cae2247d4e5 100644
--- a/libwccl/variables.h
+++ b/libwccl/variables.h
@@ -31,8 +31,9 @@ namespace detail {
 template<typename T>
 class Vmap
 {
-protected:
+public:
 	typedef std::map< std::string, boost::shared_ptr<T> > map_t;
+protected:
 	Vmap() : map_() {}
 	boost::shared_ptr<T> get(const std::string& s) const {
 		typename map_t::const_iterator i = map_.find(s);
@@ -151,7 +152,7 @@ class Variables : detail::Vmap<Value>
 	, detail::Vmap<Position>
 	, detail::Vmap<StrSet>
 	, detail::Vmap<TSet>
-//	, boost::noncopyable
+	, boost::noncopyable
 {
 public:
 	/// Valid value types, should match the inheritance.
@@ -173,12 +174,31 @@ public:
 		return detail::Vmap<T>::map_.size();
 	}
 
-	void reset_values(); //set all values to default value
+	/** Set all values to their default value.
+	  *
+	  * Effectively iterates through all variables and assigns them their
+	  * respective type's default-constructed value.
+	  */
+	void reset_values();
 
-	//template<typename T>
-	//const map_t& all_variables() const
+	/** Per-type all variables accesor.
+	 *
+	 * Allows iterating through all variables of a given type (or all variables
+	 * if the type is Value). Values may be modified, the variable names or
+	 * shared pointers themselves cannot, use put etc. for that.
+	 */
+	template<typename T>
+	const typename detail::Vmap<T>::map_t get_all() const {
+		BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+		return detail::Vmap<T>::map_;
+	}
 
-	//clone
+	/** Variables cloning.
+	 *
+	 * A clone has the same variable names, with distinct underlying Value
+	 * objects, and the same values in these objects.
+	 */
+	Variables* clone() const;
 
 	/** Get a variable.
 	 *
@@ -195,6 +215,38 @@ public:
 		return detail::Vmap<T>::get(s);
 	}
 
+	/** Get a variable, throwing version.
+	 *
+	 * Returns a valid pointer to the variable with the given name, as get(),
+	 * or throws if it is not found. Never returns NULL.
+	 *
+	 * May throw either VariableTypeMismatch or InvalidVariableName.
+	 */
+	template<typename T>
+	boost::shared_ptr<T> get_or_throw(const std::string& s) const {
+		BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+		boost::shared_ptr<T> r = detail::Vmap<T>::get(s);
+		if (r) {
+			return r;
+		} else {
+			if (detail::Vmap<Value>::get(s)) {
+				throw VariableTypeMismatch(s);
+			} else {
+				throw InvalidVariableName(s);
+			}
+		}
+	}
+
+	/** Convenience function to get the actual underlying Value of a variable.
+	 *
+	 * Will throw on errors like get_or_throw would. Returns whatever the
+	 * Value referenced returns in its get_value.
+	 */
+	template<typename T>
+	const typename T::value_type& get_value(const std::string& s) const {
+		return get_or_throw<T>(s)->get_value();
+	}
+
 	/** Create a "fast" accessor for a variable by name.
 	 *
 	 * Returns a special object which is valid for use in get_fast, which when
@@ -319,6 +371,25 @@ public:
 	 */
 	template<typename T>
 	void set(const std::string& s, const T& v);
+
+	struct AccessHelper;
+	friend struct Variables::AccessHelper;
+	struct AccessHelper
+	{
+		template<typename T>
+		typename detail::Vmap<T>::map_t& access() {
+			return vars.get_all_nonconst<T>();
+		}
+		Variables& vars;
+	private:
+		AccessHelper(Variables& v) : vars(v) {}
+		friend class Variables;
+	};
+private:
+	template<typename T>
+	typename detail::Vmap<T>::map_t& get_all_nonconst() {
+		return detail::Vmap<T>::map_;
+	}
 };
 
 /* implementation */
@@ -363,7 +434,7 @@ void Variables::put(const std::string& s, const boost::shared_ptr<T>& v) {
 template<typename T> inline
 bool Variables::del(const std::string &s)
 {
-	//BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+	BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
 	if (detail::Vmap<T>::map_.erase(s)) {
 		bool was_in_values = detail::Vmap<Value>::map_.erase(s);
 		assert(was_in_values);
@@ -380,7 +451,8 @@ bool Variables::del<Value>(const std::string &s)
 }
 
 template<typename T> inline
-void Variables::set(const std::string& s, const T& v) {
+void Variables::set(const std::string& s, const T& v)
+{
 	BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
 	boost::shared_ptr<T> p = get<T>(s);
 	if (p) {
@@ -389,6 +461,7 @@ void Variables::set(const std::string& s, const T& v) {
 		put(s, v);
 	}
 }
+
 } /* end ns Wccl */
 
 #endif // LIBWCCL_VARIABLES_H
diff --git a/tests/varaccess.cpp b/tests/varaccess.cpp
index ad4ff33293cf3d49b206d4aa7ddb839e54b7a45a..dd5d3b09225daea56531965ca9e7247548bd9a16 100644
--- a/tests/varaccess.cpp
+++ b/tests/varaccess.cpp
@@ -12,7 +12,7 @@ BOOST_AUTO_TEST_SUITE(varaccess);
 
 struct VAfx
 {
-	Variables v;
+	boost::shared_ptr<Variables> v;
 	VAfx() {
 		Variables v2;
 		v2.put("a", new Bool(true));
@@ -21,7 +21,7 @@ struct VAfx
 		v2.put("bb", new Bool(true));
 		v2.put("aa", new Position(1));
 		v2.put("aaa", new Position(2));
-		v = v2;
+		v.reset(v2.clone());
 	}
 };
 
@@ -34,19 +34,19 @@ BOOST_FIXTURE_TEST_CASE(access, VAfx)
 	vnames.push_back("c");
 	vnames.push_back("bb");
 	foreach (const std::string vn, vnames) {
-		VariableAccessor<Bool> a1 = v.create_accessor<Bool>(vn);
-		BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
-		v.set("a", Bool(false));
-		BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
-		v.put("a", Bool(true));
-		BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
+		VariableAccessor<Bool> a1 = v->create_accessor<Bool>(vn);
+		BOOST_CHECK(v->get_fast(a1) == v->get<Bool>(vn));
+		v->set("a", Bool(false));
+		BOOST_CHECK(v->get_fast(a1) == v->get<Bool>(vn));
+		v->put("a", Bool(true));
+		BOOST_CHECK(v->get_fast(a1) == v->get<Bool>(vn));
 	}
 }
 
 BOOST_FIXTURE_TEST_CASE(badaccess, VAfx)
 {
-	BOOST_CHECK_THROW(v.create_accessor<Bool>("asd"), InvalidVariableName);
-	BOOST_CHECK_THROW(v.create_accessor<Bool>("aaa"), VariableTypeMismatch);
+	BOOST_CHECK_THROW(v->create_accessor<Bool>("asd"), InvalidVariableName);
+	BOOST_CHECK_THROW(v->create_accessor<Bool>("aaa"), VariableTypeMismatch);
 }
 
 
diff --git a/tests/variables.cpp b/tests/variables.cpp
index 79cfa09d4c8bcaf0494c3c8052084e10a1c4da48..d39cf0f0a439f7670dfa5208cce3f4479a1c1d5f 100644
--- a/tests/variables.cpp
+++ b/tests/variables.cpp
@@ -80,6 +80,10 @@ BOOST_FIXTURE_TEST_CASE(get, Vfix)
 	BOOST_CHECK(v.get<Position>("p3"));
 	BOOST_CHECK(v.get<Value>("p3"));
 	BOOST_CHECK(!v.get<Bool>("p3"));
+	BOOST_CHECK_THROW(v.get_or_throw<Bool>("b9"), InvalidVariableName);
+	BOOST_CHECK_THROW(v.get_or_throw<Position>("b1"), VariableTypeMismatch);
+	BOOST_CHECK_EQUAL(v.get_or_throw<Bool>("b2"), v.get<Bool>("b2"));
+	BOOST_CHECK_EQUAL(v.get_or_throw<Position>("p2"), v.get<Position>("p2"));
 }
 
 BOOST_FIXTURE_TEST_CASE(get_put, Vfix)
@@ -141,5 +145,67 @@ BOOST_FIXTURE_TEST_CASE(del, Vfix)
 	BOOST_CHECK(!v.get<Value>("p2"));
 }
 
+BOOST_FIXTURE_TEST_CASE(get_all, Vfix)
+{
+	std::set<std::string> names;
+	foreach (const detail::Vmap<Value>::map_t::value_type& a, v.get_all<Bool>()) {
+		names.insert(a.first);
+	}
+	std::set<std::string> expected;
+	expected.insert("b1");
+	expected.insert("b2");
+	BOOST_CHECK_EQUAL_COLLECTIONS(names.begin(), names.end(), expected.begin(), expected.end());
+	names.clear();
+	foreach (const detail::Vmap<Value>::map_t::value_type& a, v.get_all<Value>()) {
+		names.insert(a.first);
+	}
+	expected.insert("p1");
+	expected.insert("p2");
+	expected.insert("p3");
+	BOOST_CHECK_EQUAL_COLLECTIONS(names.begin(), names.end(), expected.begin(), expected.end());
+}
+
+BOOST_FIXTURE_TEST_CASE(reset_values, Vfix)
+{
+	v.reset_values();
+	BOOST_CHECK_EQUAL(v.get_value<Bool>("b1"), false);
+	BOOST_CHECK_EQUAL(v.get_value<Bool>("b2"), false);
+	BOOST_CHECK_EQUAL(v.get_value<Position>("p1"), 0);
+	BOOST_CHECK_EQUAL(v.get_value<Position>("p2"), 0);
+	BOOST_CHECK_EQUAL(v.get_value<Position>("p3"), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE(clone, Vfix)
+{
+	boost::shared_ptr<Variables> copy(v.clone());
+	BOOST_CHECK_EQUAL(v.size<Value>(), copy->size<Value>());
+	BOOST_CHECK_EQUAL(v.size<Bool>(), copy->size<Bool>());
+	BOOST_CHECK_EQUAL(v.size<Position>(), copy->size<Position>());
+	foreach (const detail::Vmap<Value>::map_t::value_type& a, v.get_all<Value>()) {
+		boost::shared_ptr<Value> orig = a.second;
+		std::string name = a.first;
+		boost::shared_ptr<Value> other = copy->get<Value>(name);
+		BOOST_REQUIRE(other);
+		BOOST_CHECK(orig != other);
+		BOOST_CHECK_EQUAL(orig->to_raw_string(), other->to_raw_string());
+	}
+	foreach (const detail::Vmap<Bool>::map_t::value_type& a, v.get_all<Bool>()) {
+		boost::shared_ptr<Bool> orig = a.second;
+		std::string name = a.first;
+		boost::shared_ptr<Bool> other = copy->get<Bool>(name);
+		BOOST_REQUIRE(other);
+		BOOST_CHECK(orig != other);
+		BOOST_CHECK_EQUAL(orig->get_value(), other->get_value());
+	}
+	foreach (const detail::Vmap<Position>::map_t::value_type& a, v.get_all<Position>()) {
+		boost::shared_ptr<Position> orig = a.second;
+		std::string name = a.first;
+		boost::shared_ptr<Position> other = copy->get<Position>(name);
+		BOOST_REQUIRE(other);
+		BOOST_CHECK(orig != other);
+		BOOST_CHECK_EQUAL(orig->get_value(), other->get_value());
+	}
+}
+
 BOOST_AUTO_TEST_SUITE_END()