Index: /trunk/nv/stl/functional/hash.hh
===================================================================
--- /trunk/nv/stl/functional/hash.hh	(revision 399)
+++ /trunk/nv/stl/functional/hash.hh	(revision 400)
@@ -78,5 +78,5 @@
 	}
 
-	template < typename T, typename H = size_t >
+	template < typename T, typename H = size_t, typename Enable = void >
 	struct hash : detail::hash_base< T, H >
 	{
Index: /trunk/nv/stl/memory.hh
===================================================================
--- /trunk/nv/stl/memory.hh	(revision 399)
+++ /trunk/nv/stl/memory.hh	(revision 400)
@@ -37,6 +37,13 @@
 	{
 	public:
-		typedef T      value_type;
-		typedef size_t size_type;
+		typedef T                 value_type;
+		typedef size_t            size_type;
+		typedef ptrdiff_t         difference_type;
+		typedef value_type*       pointer;
+		typedef const value_type* const_pointer;
+		typedef value_type&       reference;
+		typedef const value_type& const_reference;
+
+
 		static constexpr bool is_static   = false;
 		static constexpr bool is_fixed    = false;
@@ -70,6 +77,12 @@
 	{
 	public:
-		typedef T        value_type;
-		typedef size_t   size_type;
+		typedef T                 value_type;
+		typedef size_t            size_type;
+		typedef ptrdiff_t         difference_type;
+		typedef const value_type* pointer;
+		typedef const value_type* const_pointer;
+		typedef const value_type& reference;
+		typedef const value_type& const_reference;
+
 		static constexpr bool is_static   = false;
 		static constexpr bool is_fixed    = false;
@@ -365,4 +378,6 @@
 		public:
 			typedef typename Super::value_type           value_type;
+			typedef const value_type*                    iterator;
+			typedef nv::reverse_iterator<iterator>       reverse_iterator;
 			typedef const value_type*                    const_iterator;
 			typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
Index: /trunk/nv/stl/string.hh
===================================================================
--- /trunk/nv/stl/string.hh	(revision 399)
+++ /trunk/nv/stl/string.hh	(revision 400)
@@ -69,5 +69,21 @@
 		};
 
-	}
+
+	}
+
+	template < typename Storage > class string_base;
+	class string_view;
+
+// Stronger version
+//	template < typename T >
+//	struct is_string_base : is_template_base_of< T, string_base > {};
+
+	template < typename T, typename Enable = void >
+	struct is_string_base : false_type {};
+	template < typename T >
+	struct is_string_base < T,
+		typename enable_if<
+		is_base_of< string_base< typename T::storage_type >, T >::value,
+		void >::type > : true_type{};
 
 	template < typename T >
@@ -76,20 +92,22 @@
 
 	};
-	
-	class string_view;
 
 	// string base class - will become a base for a string class later
-	class string_base : public detail::add_iterators< storage_view< char > >
-	{
-		typedef detail::add_iterators< storage_view< char > > inherited;
+	template < typename Storage >
+	class string_base : public detail::add_iterators< Storage >
+	{
+		typedef detail::add_iterators< Storage >                base_type;
+		typedef string_base< detail::add_iterators< Storage > > this_type;
 	public:
-		typedef char           value_type;
-		typedef const char*    pointer;
-		typedef const char&    reference;
-		typedef const char&    const_reference;
-		typedef pointer        const_iterator;
-		typedef const_iterator iterator;
-		typedef size_t         size_type;
-		typedef ptrdiff_t      difference_type;
+		typedef Storage                             storage_type;
+		typedef typename base_type::value_type      value_type;
+		typedef typename base_type::pointer         pointer;
+		typedef typename base_type::const_pointer   const_pointer;
+		typedef typename base_type::reference       reference;
+		typedef typename base_type::const_reference const_reference;
+		typedef typename base_type::iterator        iterator;
+		typedef typename base_type::const_iterator  const_iterator;
+		typedef typename base_type::size_type       size_type;
+		typedef typename base_type::difference_type difference_type;
 
 		static constexpr size_type npos = size_type( -1 );
@@ -104,6 +122,6 @@
 
 		// access
-		inline char operator[]( size_type i ) const { return data()[i]; }
-		inline char at( size_type i ) const
+		inline value_type operator[]( size_type i ) const { return data()[i]; }
+		inline value_type at( size_type i ) const
 		{
 			//	if ( i >= m_data ) NV_THROW( out_of_range( "string_ref::at" ) );
@@ -111,174 +129,94 @@
 		}
 
-		inline char front()        const { return data()[0]; }
-		inline char back()         const { return data()[size() - 1]; }
+		inline value_type front()        const { return data()[0]; }
+		inline value_type back()         const { return data()[size() - 1]; }
 
 		// string operations
-		int compare( const string_base& rhs ) const
-		{
-			size_type this_size = size();
-			int cmp = nvmemcmp( data(), rhs.data(), ( nv::min )( this_size, rhs.size() ) );
-			return cmp != 0 ? cmp : ( this_size == rhs.size() ? 0 : this_size < rhs.size() ? -1 : 1 );
-		}
-		bool starts_with( char c ) const { return !empty() && c == front(); }
-		bool starts_with( const string_base& s ) const
-		{
-			return size() >= s.size() && nvmemcmp( data(), s.data(), s.size() ) == 0;
-		}
-		bool ends_with( char c ) const { return !empty() && c == back(); }
-		bool ends_with( const string_base& s ) const
-		{
-			return size() >= s.size() && nvmemcmp( data() + size() - s.size(), s.data(), s.size() ) == 0;
-		}
-		size_type find( const string_base& s, size_type pos = 0 ) const
-		{
-			if ( pos >= size() ) return npos;
-			const_iterator it = search( this->cbegin() + ( difference_type ) pos, this->cend(), s.cbegin(), s.cend() );
-			return it == this->cend() ? npos : ( size_type )distance( this->cbegin(), it );
-		}
-		size_type find( char c, size_type pos = 0 ) const
-		{
-			if ( pos >= size() ) return npos;
-			const_iterator it = find_if( this->cbegin() + (difference_type)pos, this->cend(), [=] ( char val ) { return val == c; } );
-			return it == this->cend() ? npos : ( size_type )distance( this->cbegin(), it );
-		}
-		size_type rfind( const string_base& s, size_type pos = 0 ) const
-		{
-			if ( pos >= size() ) return npos;
-			const_reverse_iterator it = search( this->crbegin() + (difference_type)pos, this->crend(), s.crbegin(), s.crend() );
-			return it == this->crend() ? npos : reverse_distance( this->crbegin(), it );
-		}
-		size_type rfind( char c, size_type pos = 0 ) const
-		{
-			if ( pos >= size() ) return npos;
-			const_reverse_iterator it = find_if( this->crbegin() + (difference_type)pos, this->crend(), [=] ( char val ) { return val == c; } );
-			return it == this->crend() ? npos : reverse_distance( this->crbegin(), it );
-		}
-		size_type find_first_of( char c ) const { return find( c ); }
-		size_type find_first_of( const string_base& s ) const
-		{
-			const_iterator it = nv::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend() );
-			return it == this->cend() ? npos : ( size_type )distance( this->cbegin(), it );
-		}
-		size_type find_last_of( char c )  const { return rfind( c ); }
-		size_type find_last_of( const string_base& s ) const
-		{
-			const_reverse_iterator it = nv::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend() );
-			return it == this->crend() ? npos : reverse_distance( this->crbegin(), it );
-		}
-		size_type find_first_not_of( const string_base& s ) const
-		{
-			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
-				if ( 0 == nvmemchr( s.data(), (uchar8)*it, s.size() ) )
-					return ( size_type )distance( this->cbegin(), it );
-			return npos;
-		}
-		size_type find_first_not_of( char c ) const
-		{
-			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
-				if ( c != *it )
-					return ( size_type )distance( this->cbegin(), it );
-			return npos;
-		}
-		size_type find_last_not_of( const string_base& s ) const
-		{
-			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
-				if ( 0 == nvmemchr( s.data(), (uchar8)*it, s.size() ) )
-					return reverse_distance( this->crbegin(), it );
-			return npos;
-		}
-		size_type find_last_not_of( char c ) const
-		{
-			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
-				if ( c != *it )
-					return reverse_distance( this->crbegin(), it );
-			return npos;
-		}
+		int compare( const string_view& rhs ) const;
+		bool starts_with( value_type c ) const;
+		bool starts_with( const string_view& s ) const;
+		bool ends_with( value_type c ) const;
+		bool ends_with( const string_view& s ) const;
+		auto find( value_type c, size_type pos = 0 ) const -> size_type;
+		auto find( const string_view& s, size_type pos = 0 ) const -> size_type;
+		auto rfind( value_type c, size_type pos = 0 ) const -> size_type;
+		auto rfind( const string_view& s, size_type pos = 0 ) const -> size_type;
+		auto find_first_of( value_type c ) const -> size_type;
+		auto find_first_of( const string_view& s ) const -> size_type;
+		auto find_last_of( value_type c )  const -> size_type;
+		auto find_last_of( const string_view& s ) const -> size_type;
+		auto find_first_not_of( value_type c ) const -> size_type;
+		auto find_first_not_of( const string_view& s ) const -> size_type;
+		auto find_last_not_of( value_type c ) const -> size_type;
+		auto find_last_not_of( const string_view& s ) const -> size_type;
 
 		// string operations
 		string_view substr( size_type p, size_type n = npos ) const;
 
-		inline size_t hash() const
-		{
-			return hash_string< size_t >( data(), size() );
+		template < typename H = size_type >
+		inline H hash() const
+		{
+			return hash_string< size_type >( this->data(), this->size() );
+		}
+
+	protected:
+		using base_type::base_type;
+
+		template < typename ReverseIterator >
+		size_type reverse_distance( ReverseIterator first, ReverseIterator last ) const
+		{
+			return this->size() - 1 - (size_t)nv::distance( first, last );
+		}
+	};
+
+	template< typename T, typename H >
+	struct hash< T, H, typename enable_if< is_string_base<T>::value, void >::type >
+	{
+		static H get( const T& value )
+		{
+			return value.hash< H >();
+		}
+		inline H operator()( const T& value ) const { return get( value ); }
+	};
+
+	class string_view : public string_base< storage_view< char > >
+	{
+	public:
+		typedef string_base< storage_view< char > > this_type;
+
+		inline string_view() {}
+		inline string_view( const string_view& rhs )
+			: this_type( rhs.data(), rhs.size() )
+		{
+		}
+		template < typename S >
+		inline string_view( const string_base<S>& rhs )
+			: this_type( rhs.data(), rhs.size() )
+		{
+		}
+
+		inline string_view( const std::string& str )
+			: this_type( str.data(), str.size() )
+		{
+		}
+
+		inline string_view( const char* str, size_type len )
+			: this_type( str, len )
+		{
 		}
 
 		// Literal constructors
 		template< size_t N >
-		inline string_base( char( &s )[N] ) : inherited( s, N - 1 ) {}
+		inline string_view( char( &s )[N] ) : this_type( s, N - 1 ) {}
 		template< size_t N >
-		inline string_base( const char( &s )[N] ) : inherited( s, N - 1 ) {}
-
-	protected:
-		inline string_base() {}
-		inline string_base( pointer a_data, size_type a_lenght ) : inherited( a_data, a_lenght ) {}
-
-		template < typename ReverseIterator >
-		size_type reverse_distance( ReverseIterator first, ReverseIterator last ) const
-		{
-			return size() - 1 - (size_t)distance( first, last );
-		}
-	};
-
-	template< typename H >
-	struct hash< string_base, H >
-	{
-		static H get( const string_base& value )
-		{
-			return hash_string< H >( value.data(), value.length() );
-		}
-		inline H operator()( const string_base& value ) const { return get( value ); }
-	};
-
-	class literal_string : public string_base
-	{
-	public:
-		// Literal constructors
-		template< size_t N >
-		inline literal_string( char( &s )[N] ) : string_base( s, N - 1 ) {}
-		template< size_t N >
-		inline literal_string( const char( &s )[N] ) : string_base( s, N - 1 ) {}
-	};
-
-	template< typename H >
-	struct hash< literal_string, H > : hash< string_base, H >{};
-
-
-	class string_view : public string_base
-	{
-	public:
-		inline string_view() {}
-		inline string_view( const string_view& rhs )
-			: string_base( rhs.data(), rhs.size() )
-		{
-		}
-		inline string_view( const string_base& rhs )
-			: string_base( rhs.data(), rhs.size() )
-		{
-		}
-
-		inline string_view( const std::string& str )
-			: string_base( str.data(), str.size() )
-		{
-		}
-
-		inline string_view( const char* str, size_type len )
-			: string_base( str, len )
-		{
-		}
-
-		// Literal constructors
-		template< size_t N >
-		inline string_view( char( &s )[N] ) : string_base( s, N - 1 ) {}
-		template< size_t N >
-		inline string_view( const char( &s )[N] ) : string_base( s, N - 1 ) {}
+		inline string_view( const char( &s )[N] ) : this_type( s, N - 1 ) {}
 
 		// Non-literal constructors
 		template< typename U >
-		inline string_view( U str, typename enable_if<is_same<U, const char*>::value>::type* = nullptr ) : string_base( str, nvstrlen( str ) ) {}
+		inline string_view( U str, typename enable_if<is_same<U, const char*>::value>::type* = nullptr ) : this_type( str, nvstrlen( str ) ) {}
 
 		// Non-literal constructors
 		template< typename U >
-		inline string_view( U str, typename enable_if<is_same<U, char*>::value>::type* = nullptr ) : string_base( str, nvstrlen( str ) ) {}
+		inline string_view( U str, typename enable_if<is_same<U, char*>::value>::type* = nullptr ) : this_type( str, nvstrlen( str ) ) {}
 
 		inline string_view& operator=( const string_view &rhs )
@@ -308,81 +246,144 @@
 	};
 
-	template< typename H >
-	struct hash< string_view, H > : hash< string_base, H >{};
-
-	// const string is movable but not copyable
-	class const_string : public string_base
-	{
-	public:
-		inline const_string() {}
-		inline const_string( const char* str, size_type len )
-		{
-			initialize( str, len );
-		}
-		inline explicit const_string( const char* str )
-		{
-			initialize( str, nvstrlen( str ) );
-		}
-
-		~const_string()
-		{
-			if ( data() )
-			{
-				delete data();
-			}
-		}
-
-		inline const_string( const_string&& other )
-		{
-			assign( other.data(), other.size() );
-			other.assign( nullptr, 0 );
-		}
-
-		inline const_string& operator=( const_string&& other )
-		{
-			pointer   old_data = data();
-			size_type old_size = size();
-			assign( other.data(), other.size() );
-			other.assign( old_data , old_size );
-			return *this;
-		}
-
-		// blocked copy constructor
-		const_string( const const_string & ) = delete;
-		// blocked copy operator
-		const_string& operator=( const const_string& ) = delete;
-
-	private:
-
-		void initialize( const char* p, size_type s )
-		{
-			char* data = new char[s + 1];
-			nvmemcpy( data, p, s );
-			data[s] = 0;
-			assign( data, s );
-		}
-	};
-
-	inline string_view string_base::substr( size_type p, size_type n ) const
-	{
-		if ( p > size() ) return string_view(); // NV_THROW( out_of_range( "substr" ) );
-		if ( n == p || p + n > size() ) n = size() - p;
-		return string_view( data() + p, n );
+	template < typename Storage >
+	inline int string_base< Storage >::compare( const string_view& rhs ) const
+	{
+		size_type this_size = this->size();
+		int cmp = nvmemcmp( this->data(), rhs.data(), ( nv::min )( this_size, rhs.size() ) );
+		return cmp != 0 ? cmp : ( this_size == rhs.size() ? 0 : this_size < rhs.size() ? -1 : 1 );
+	}
+
+	template < typename Storage >
+	inline bool string_base< Storage >::starts_with( value_type c ) const 
+	{ 
+		return !this->empty() && c == this->front(); 
+	}
+	template < typename Storage >
+	inline bool string_base< Storage >::starts_with( const string_view& s ) const
+	{
+		return this->size() >= s.size() && nvmemcmp( this->data(), s.data(), s.size() ) == 0;
+	}
+
+	template < typename Storage >
+	inline bool string_base< Storage >::ends_with( value_type c ) const 
+	{ 
+		return !this->empty() && c == this->back();
+	}
+	template < typename Storage >
+	inline bool string_base< Storage >::ends_with( const string_view& s ) const
+	{
+		return this->size() >= s.size() && nvmemcmp( this->data() + this->size() - s.size(), s.data(), s.size() ) == 0;
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::find( value_type c, size_type pos = 0 ) const -> size_type
+	{
+		if ( pos >= this->size() ) return npos;
+		const_iterator it = nv::find_if( this->cbegin() + (difference_type)pos, this->cend(), [=] ( value_type val ) { return val == c; } );
+		return it == this->cend() ? npos : (size_type)nv::distance( this->cbegin(), it );
+	}
+	template < typename Storage >
+	inline auto string_base< Storage >::find( const string_view& s, size_type pos = 0 ) const -> size_type
+	{
+		if ( pos >= this->size() ) return npos;
+		const_iterator it = nv::search( this->cbegin() + (difference_type)pos, this->cend(), s.cbegin(), s.cend() );
+		return it == this->cend() ? npos : (size_type)nv::distance( this->cbegin(), it );
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::rfind( value_type c, size_type pos = 0 ) const -> size_type
+	{
+		if ( pos >= this->size() ) return npos;
+		const_reverse_iterator it = nv::find_if( this->crbegin() + (difference_type)pos, this->crend(), [=] ( value_type val ) { return val == c; } );
+		return it == this->crend() ? npos : this->reverse_distance( this->crbegin(), it );
+	}
+	template < typename Storage >
+	inline auto string_base< Storage >::rfind( const string_view& s, size_type pos = 0 ) const -> size_type
+	{
+		if ( pos >= this->size() ) return npos;
+		const_reverse_iterator it = nv::search( this->crbegin() + (difference_type)pos, this->crend(), s.crbegin(), s.crend() );
+		return it == this->crend() ? npos : this->reverse_distance( this->crbegin(), it );
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::find_first_of( value_type c ) const -> size_type
+	{
+		return this->find( c );
+	}
+	template < typename Storage >
+	inline auto string_base< Storage >::find_first_of( const string_view& s ) const -> size_type
+	{
+		const_iterator it = nv::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend() );
+		return it == this->cend() ? npos : (size_type)nv::distance( this->cbegin(), it );
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::find_last_of( value_type c ) const -> size_type
+	{
+		return this->rfind( c );
+	} 
+	template < typename Storage >
+	inline auto string_base< Storage >::find_last_of( const string_view& s ) const -> size_type
+	{
+		const_reverse_iterator it = nv::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend() );
+		return it == this->crend() ? npos : this->reverse_distance( this->crbegin(), it );
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::find_first_not_of( value_type c ) const -> size_type
+	{
+		for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
+			if ( c != *it )
+			return (size_type)distance( this->cbegin(), it );
+		return npos;
+	}
+	template < typename Storage >
+	inline auto string_base< Storage >::find_first_not_of( const string_view& s ) const -> size_type
+	{
+		for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
+			if ( 0 == nvmemchr( s.data(), (uchar8)*it, s.size() ) )
+			return (size_type)distance( this->cbegin(), it );
+		return npos;
+	}
+
+	template < typename Storage >
+	inline auto string_base< Storage >::find_last_not_of( value_type c ) const -> size_type
+	{
+		for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
+			if ( c != *it )
+			return this->reverse_distance( this->crbegin(), it );
+		return npos;
+	}
+	template < typename Storage >
+	inline auto string_base< Storage >::find_last_not_of( const string_view& s ) const -> size_type
+	{
+		for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
+			if ( 0 == nvmemchr( s.data(), (uchar8)*it, s.size() ) )
+			return this->reverse_distance( this->crbegin(), it );
+		return npos;
+	}
+
+	template < typename Storage >
+	inline string_view string_base< Storage >::substr( size_type p, size_type n ) const
+	{
+		if ( p > this->size() ) return string_view(); // NV_THROW( out_of_range( "substr" ) );
+		if ( n == p || p + n > this->size() ) n = this->size() - p;
+		return string_view( this->data() + p, n );
 	}
 
 #define NV_STRING_BASE_CAST_OPERATORS( OPERATOR )\
-inline bool operator OPERATOR ( const string_base& lhs, const std::string& rhs )\
+template < typename S > inline bool operator OPERATOR ( const string_base< S >& lhs, const std::string& rhs )\
 {\
 	return lhs OPERATOR string_view( rhs );\
 }\
-inline bool operator OPERATOR ( const std::string& lhs, const string_base& rhs )\
+template < typename S > inline bool operator OPERATOR ( const std::string& lhs, const string_base< S >& rhs )\
 {\
 	return string_view( lhs ) OPERATOR rhs;\
 }\
-inline bool operator OPERATOR ( const string_base& lhs, const char* rhs )\
+template < typename S > inline bool operator OPERATOR ( const string_base< S >& lhs, const char* rhs )\
 {\
 	return lhs OPERATOR string_view( rhs );\
 }\
-inline bool operator OPERATOR ( const char* lhs, const string_base& rhs )\
+template < typename S > inline bool operator OPERATOR ( const char* lhs, const string_base< S >& rhs )\
 {\
 	return string_view( lhs ) OPERATOR rhs;\
@@ -390,25 +391,31 @@
 
 	// Base operators
-	inline bool operator==( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator==( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 );
 	}
-	inline bool operator!=( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator!=( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 );
 	}
-	inline bool operator<( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator<( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.compare( rhs ) < 0;
 	}
-	inline bool operator>( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator>( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.compare( rhs ) > 0;
 	}
-	inline bool operator<=( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator<=( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.compare( rhs ) <= 0;
 	}
-	inline bool operator>=( const string_base& lhs, const string_base& rhs )
+	template < typename S1, typename S2 >
+	inline bool operator>=( const string_base< S1 >& lhs, const string_base< S2 >& rhs )
 	{
 		return lhs.compare( rhs ) >= 0;
@@ -431,4 +438,70 @@
 size_t f32_to_buffer( f32 n, char* str );
 size_t f64_to_buffer( f64 n, char* str );
+
+	// const string is movable but not copyable
+	class const_string : public string_base< storage_view< char > >
+	{
+	public:
+		inline const_string() {}
+		inline const_string( const char* str, size_type len )
+		{
+			initialize( str, len );
+		}
+		inline explicit const_string( const char* str )
+		{
+			initialize( str, nvstrlen( str ) );
+		}
+
+		~const_string()
+		{
+			if ( data() )
+			{
+				delete data();
+			}
+		}
+
+		inline const_string( const_string&& other )
+		{
+			assign( other.data(), other.size() );
+			other.assign( nullptr, 0 );
+		}
+
+		inline const_string& operator=( const_string&& other )
+		{
+			pointer   old_data = data();
+			size_type old_size = size();
+			assign( other.data(), other.size() );
+			other.assign( old_data , old_size );
+			return *this;
+		}
+
+		// blocked copy constructor
+		const_string( const const_string & ) = delete;
+		// blocked copy operator
+		const_string& operator=( const const_string& ) = delete;
+
+	private:
+
+		void initialize( const char* p, size_type s )
+		{
+			char* new_data = new char[s + 1];
+			nvmemcpy( new_data, p, s );
+			new_data[s] = 0;
+			assign( new_data, s );
+		}
+	};
+
+	class literal_string : public string_base< storage_view< char > >
+	{
+	public:
+		typedef string_base< storage_view< char > > this_type;
+
+		// Literal constructors
+		template< size_t N >
+		inline literal_string( char( &s )[N] ) : this_type( s, N - 1 ) {}
+		template< size_t N >
+		inline literal_string( const char( &s )[N] ) : this_type( s, N - 1 ) {}
+	};
+
 
 inline string_view trimmed( const string_view& str )
Index: /trunk/nv/stl/type_traits/properties.hh
===================================================================
--- /trunk/nv/stl/type_traits/properties.hh	(revision 399)
+++ /trunk/nv/stl/type_traits/properties.hh	(revision 400)
@@ -284,4 +284,20 @@
 #endif
 
+	namespace detail
+	{
+		template < typename T, template<typename...> class Template >
+		class is_template_base_of_impl : sfinae_types
+		{
+			template < typename... Args >
+			static size_one test( const Template< Args... >* );
+			static size_two test( ... );
+		public:
+			static constexpr bool value = sizeof( test<T>( 0 ) ) == 1;
+		};
+	}
+
+	template < typename T, template<typename...> class Template >
+	struct is_template_base_of : bool_constant< detail::is_template_base_of_impl< T, Template >::value > {};
+
 
 // TODO: non-standard, remove?
