diff --git a/libwccl/variables.cpp b/libwccl/variables.cpp
index 3b2c9a02368eabad146e36b15e012998863ff7cb..419c44e210c71441339ca54012602a56a11a9b87 100644
--- a/libwccl/variables.cpp
+++ b/libwccl/variables.cpp
@@ -1,35 +1,69 @@
 #include <libwccl/variables.h>
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/pop_front.hpp>
 
 namespace Wccl {
 
 Variables::Variables()
-	: map_()
 {
 }
 
-void Variables::put(const std::string &name, Value *value)
+namespace {
+struct delhelper
 {
-	map_[name] = value;
-}
+	Variables& v;
+	const std::string& s;
+	bool& r;
+	delhelper(Variables& v, const std::string& s, bool& r): v(v), s(s), r(r) {}
+
+	template<typename T>
+	void operator()(const boost::mpl::always<T>&) {
+		r = v.del<T>(s) || r;
+	}
+};
 
-Value* Variables::get_or_null(const std::string &name)
+struct puthelper
 {
-	map_t::iterator i = map_.find(name);
-	if (i != map_.end()) {
-		return i->second;
-	} else {
-		return NULL;
+	Variables& v;
+	const std::string& s;
+	bool& rv;
+	const boost::shared_ptr<Value>& p;
+	puthelper(Variables& v, const std::string& s, bool& rv,
+		const boost::shared_ptr<Value>& p): v(v), s(s), rv(rv), p(p) {}
+
+	template<typename T>
+	void operator()(const boost::mpl::always<T>&) {
+		if (rv) return;
+		boost::shared_ptr<T> t = boost::dynamic_pointer_cast<T>(p);
+		if (t) {
+			rv = true;
+			v.put(s, t);
+		}
 	}
+};
+
+} /* 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;
 }
 
-const Value* Variables::get_or_null(const std::string &name) const
+void Variables::put_any(const std::string &s, const boost::shared_ptr<Value> &v)
 {
-	map_t::const_iterator i = map_.find(name);
-	if (i != map_.end()) {
-		return i->second;
-	} else {
-		return NULL;
-	}
+	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);
 }
 
 } /* end ns Wccl */
diff --git a/libwccl/variables.h b/libwccl/variables.h
index 039d11a168daccab0d6a7bacc1c59d1033cf42e5..6f124de3d70a6c8c98dee1e9e626e5e3f179cb79 100644
--- a/libwccl/variables.h
+++ b/libwccl/variables.h
@@ -1,69 +1,278 @@
 #ifndef LIBWCCL_VARIABLES_H
 #define LIBWCCL_VARIABLES_H
 
-#include <libwccl/value.h>
+#include <libwccl/bool.h>
+#include <libwccl/exception.h>
+#include <libwccl/position.h>
+#include <iostream>
+#include <map>
+#include <string>
+#include <cassert>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/count.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/list.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_base_of.hpp> 
+#include <boost/type_traits/is_same.hpp>
 
 namespace Wccl {
 
+namespace detail {
+
 /**
- * A class for holding values by name.
+ * Helper class template for the Variables class to facilitate
+ * per-type maps.
  */
-class Variables
+template<typename T>
+class Vmap
+{
+protected:
+	typedef std::map< std::string, boost::shared_ptr<T> > map_t;
+	Vmap() : map_() {}
+	boost::shared_ptr<T> get(const std::string& s) const {
+		typename map_t::const_iterator i = map_.find(s);
+		if (i != map_.end()) {
+			return i->second;
+		} else {
+			return boost::shared_ptr<T>();
+		}
+	}
+	map_t map_;
+};
+
+} /* end ns detail */
+
+/**
+ * Exception class for variable type mismatches
+ */
+class VariableTypeMismatch : public WcclError
 {
 public:
-	/// Ctor.
+	VariableTypeMismatch(const std::string& varname)
+	 : WcclError("Variable type mismatch"), varname(varname)
+	{}
+
+	~VariableTypeMismatch() throw() {}
+
+	std::string varname;
+};
+
+/**
+ * A class for holding variables.
+ *
+ * Variables are values with a name. They can any of the allowed types,
+ * but only one variable, of one type, can exist under one name, so it is
+ * not allowed to have an ambiguous variable name.
+ * 
+ * Values are kept as shared pointers and returned as such.
+ *
+ * Variables are manipulated by name using specific type overloads, and also
+ * by the Value overload that, if possible, works across all valid types.
+ * Some functions can only work for a concrete Value derived class, they are
+ * marked as such and guarded by compile-time checks.
+ *
+ * Values are subtypes of the Value class, valid types are listed as arguments
+ * of instantiations of the detail::Vmap base class template, and in the type
+ * list below. Adding a new subtype should only take adding it to these two
+ * places.
+ */
+class Variables : detail::Vmap<Value>
+	, detail::Vmap<Bool>
+	, detail::Vmap<Position>
+{
+public:
+	/// Valid value types, should match the inheritance.
+	/// the type Value must be first, order of other items is not important
+	typedef boost::mpl::list<Value, Bool, Position> types;
+
+	/// Constructor, creates an empty instance.
 	Variables();
 
-	/**
-	 * Set the variable with the given name to the given value.
+	/** Per-type size checker.
+	 *
+	 * Use the Value type to count all variables. In C++0x, Value would be
+	 * the default template argument.
+	 */
+	template<typename T>
+	int size() const {
+		BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+		return detail::Vmap<T>::map_.size();
+	}
+
+	/** Get a variable.
+	 *
+	 * Returns the variable with the given name, or NULL if it does not exist.
+	 * Use a specialied version with the requested type, or the general Value 
+	 * type if looking for any variable.
+	 * 
+	 * If T is not Value and the variable exists but has a different type,
+	 * returns NULL as if the variable did not exist.
+	 */
+	template<typename T>
+	boost::shared_ptr<T> get(const std::string& s) const {
+		BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+		return detail::Vmap<T>::get(s);
+	}
+
+	/** Get a variable, possibly default-creatng it.
+	 *
+	 * Returns the variable with the given name, or, if it does not exist,
+	 * creates a new empty variable of the type given as the template
+	 * parameter and returns that.
+	 *
+	 * The variable must be of the requested type, otherwise
+	 * VariableTypeMismatch is thrown.
+	 * 
+	 * The function cannot be called if T is Value since T must be
+	 * constructible.
+	 */
+	template<typename T>
+	boost::shared_ptr<T> get_put(const std::string& s); 
+
+	/** Add a variable with the given name and the given value.
+	 *
+	 * The type should be normally deduced by the compiler, and should be 
+	 * a subtype of Value. Value itself can not be used, but @see put_any.
 	 *
 	 * If the variable does not exist, it is created.
-	 * If it already exists, the value is replaced.
+	 *
+	 * If it already exists it is replaced provided that the current type
+	 * matches (if it does not, VariableTypeMismatch is thrown). This
+	 * replacement is different from a set(s, v) since the original
+	 * value is not modified.
 	 */
-	void put(const std::string& name, Value* value);
+	template<typename T>
+	void put(const std::string& s, const boost::shared_ptr<T>& v);
 
-	/**
-	 * Get the value of the variable with the given name, or, if it does not
-	 * exist, NULL.
+	/** Add a variable with the given name and the given value, dynamically
+	 * deducing the actual type.
+	 *
+	 * Prefer put<T> with a concrete T since it will be faster.
+	 *
+	 * @see the put version with a concrete type for semantics since
+	 * it is called eventually.
+	 *
+	 * The first matching type (where a dynamic_cast succeeds) is used.
+	 * If the passed Value cannot be converted to a valid subtype,
+	 * VariableTypeMismatch is thrown.
+	 */
+	void put_any(const std::string& s, const boost::shared_ptr<Value>& v);
+
+	/** Remove a variable assuming it has the given type.
+	 *
+	 * When T is Value, equivalent to del_any.
+	 *
+	 * @returns true if the variable was removed, false otherwise
 	 */
-	Value* get_or_null(const std::string& name);
+	template<typename T>
+	bool del(const std::string& s);
 
-	/**
-	 * Get the value of the variable with the given name, or, if it does not
-	 * exist, NULL. Const.
+	/** Remove a variable regardless of it's type.
+	 *
+	 * Prefer del<T> with a concrete T as it will be faster.
+	 *
+	 * @returns true if the variable was removed, false otherwise
 	 */
-	const Value* get_or_null(const std::string &name) const;
+	bool del_any(const std::string& s);
 
-	/**
-	 * Get the value of the variable with th egiven name, or, if it does not
-	 * exist, create a new empty variable of the type given as the template
-	 * parameter and return that.
+	/** Put<T> convenience overload for raw pointers that wraps them in a
+	 * shared_ptr (thus taking ownership).
 	 */
 	template<typename T>
-	Value* get_or_put(const std::string& name) {
-		map_t::iterator i = map_.find(name);
-		if (i != map_.end()) {
-			return i->second;
+	void put(const std::string& s, T* v) {
+		put(s, boost::shared_ptr<T>(v));
+	}
+
+	/** Convenience function for putting raw values (not pointers)
+	 * that will allocate a copy as a shared pointer.
+	 */
+	template<typename T>
+	void put(const std::string& s, const T& v) {
+		put(s, boost::make_shared<T>(v));
+	}
+
+	/** Set an existing variable to the given value, or create a new variable.
+	 *
+	 * If the variable with the given name does not exist, it is created.
+	 * If it exists, it is set to the passed value (modified in-place).
+	 * This is in contrast to put(s, v) which would leave the original value
+	 * unchanged.
+	 */
+	template<typename T>
+	void set(const std::string& s, const T& v);
+};
+
+/* implementation */
+
+template<typename T> inline
+boost::shared_ptr<T> Variables::get_put(const std::string& s)
+{
+	BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+	boost::shared_ptr<T> v = get<T>(s);
+	if (!v) {
+		if (!get<Value>(s)) {
+			v.reset(new T());
+			put(s, v);
 		} else {
-			return map_.insert(std::make_pair(name, new T()))->second;
+			throw VariableTypeMismatch(s);
 		}
 	}
+	return v;
+}
 
-	/// Typdef for the map type
-	typedef std::map<std::string, Value*> map_t;
 
-	/**
-	 * Const map accesor, for iterating through all variables
-	 */
-	const map_t& all_variables() const {
-		return map_;
+template<typename T> inline
+void Variables::put(const std::string& s, const boost::shared_ptr<T>& v) {
+	BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
+	// disable put<Value>
+	BOOST_MPL_ASSERT_NOT(( boost::is_same<T, Value> ));
+	using detail::Vmap;
+	typename Vmap<T>::map_t::iterator i = Vmap<T>::map_.find(s);
+	typename Vmap<Value>::map_t::iterator vi = Vmap<Value>::map_.find(s);
+	if (i != Vmap<T>::map_.end()) {
+		assert(vi != Vmap<Value>::map_.end()); //invariant
+		i->second = v;
+		vi->second = v;
+	} else if (vi == Vmap<Value>::map_.end()) {
+		Vmap<T>::map_[s] = v;
+		Vmap<Value>::map_[s] = v;
+	} else {
+		throw VariableTypeMismatch(s);
 	}
+}
 
-private:
-	/// The variables map
-	map_t map_;
-};
+template<typename T> inline
+bool Variables::del(const std::string &s)
+{
+	//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);
+		return true;
+	} else {
+		return false;
+	}
+}
+
+template<> inline
+bool Variables::del<Value>(const std::string &s)
+{
+	return del_any(s);
+}
 
+template<typename T> inline
+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) {
+		*p = v;
+	} else {
+		put(s, v);
+	}
+}
 } /* end ns Wccl */
 
 #endif // LIBWCCL_VARIABLES_H