Index: /trunk/nv/stl/iterator.hh
===================================================================
--- /trunk/nv/stl/iterator.hh	(revision 406)
+++ /trunk/nv/stl/iterator.hh	(revision 407)
@@ -104,22 +104,22 @@
 
 	public:
-		reverse_iterator() : m_base() {}
-		explicit reverse_iterator( iterator_type i ) : m_base( i ) {}
+		constexpr reverse_iterator() : m_base() {}
+		constexpr explicit reverse_iterator( iterator_type i ) : m_base( i ) {}
 
 		template <typename U>
-		reverse_iterator( const reverse_iterator<U>& ri ) : m_base( ri.base() ) {}
-
-		iterator_type base() const { return m_base; }
-		reference operator*( ) const { iterator_type i( m_base ); return *--i; }
-		pointer operator->( ) const { return &( operator*( ) ); }
-		reverse_iterator& operator++( ) { --m_base; return *this; }
-		reverse_iterator operator++( int ) { reverse_iterator ri( *this ); --m_base; return ri; }
-		reverse_iterator& operator--( ) { ++m_base; return *this; }
-		reverse_iterator operator--( int ) { reverse_iterator ri( *this ); ++m_base; return ri; }
-		reverse_iterator operator+( difference_type n ) const { return reverse_iterator( m_base - n ); }
-		reverse_iterator& operator+=( difference_type n ) { m_base -= n; return *this; }
-		reverse_iterator operator-( difference_type n ) const { return reverse_iterator( m_base + n ); }
-		reverse_iterator& operator-=( difference_type n ) { m_base += n; return *this; }
-		reference operator[]( difference_type n ) const { return m_base[-n - 1]; }
+		constexpr reverse_iterator( const reverse_iterator<U>& ri ) : m_base( ri.base() ) {}
+
+		constexpr iterator_type base() const { return m_base; }
+		inline reference operator*( ) const { iterator_type i( m_base ); return *--i; }
+		inline pointer operator->( ) const { return &( operator*( ) ); }
+		inline reverse_iterator& operator++( ) { --m_base; return *this; }
+		inline reverse_iterator operator++( int ) { reverse_iterator ri( *this ); --m_base; return ri; }
+		inline reverse_iterator& operator--( ) { ++m_base; return *this; }
+		inline reverse_iterator operator--( int ) { reverse_iterator ri( *this ); ++m_base; return ri; }
+		inline reverse_iterator operator+( difference_type n ) const { return reverse_iterator( m_base - n ); }
+		inline reverse_iterator& operator+=( difference_type n ) { m_base -= n; return *this; }
+		inline reverse_iterator operator-( difference_type n ) const { return reverse_iterator( m_base + n ); }
+		inline reverse_iterator& operator-=( difference_type n ) { m_base += n; return *this; }
+		constexpr reference operator[]( difference_type n ) const { return m_base[-n - 1]; }
 	protected:
 		iterator_type m_base;
@@ -127,25 +127,25 @@
 
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator==( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
+	constexpr bool operator==( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
 	{ return lhs.base() == rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator!=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
+	constexpr bool operator!=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
 	{ return lhs.base() != rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator<( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
+	constexpr bool operator<( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator< Iterator2 >& rhs )
 	{ return lhs.base() > rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator>( const reverse_iterator< Iterator1>& lhs, const reverse_iterator< Iterator2 >& rhs )
+	constexpr bool operator>( const reverse_iterator< Iterator1>& lhs, const reverse_iterator< Iterator2 >& rhs )
 	{ return lhs.base() < rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator<=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator<Iterator2 >& rhs )
+	constexpr bool operator<=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator<Iterator2 >& rhs )
 	{ return lhs.base() >= rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline bool operator>=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator<Iterator2 >& rhs )
+	constexpr bool operator>=( const reverse_iterator< Iterator1 >& lhs, const reverse_iterator<Iterator2 >& rhs )
 	{ return lhs.base() <= rhs.base(); }
 	template < typename Iterator1, typename Iterator2 >
-	inline typename reverse_iterator<Iterator1>::difference_type operator-( const reverse_iterator<Iterator1>& lhs, const reverse_iterator<Iterator2>& rhs )
+	constexpr typename reverse_iterator<Iterator1>::difference_type operator-( const reverse_iterator<Iterator1>& lhs, const reverse_iterator<Iterator2>& rhs )
 	{ return rhs.base() - lhs.base(); }
-	template < typename Iterator > inline reverse_iterator<Iterator> operator+( typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& iter )
+	template < typename Iterator > constexpr reverse_iterator<Iterator> operator+( typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& iter )
 	{ return reverse_iterator<Iterator>( iter.base() - n ); }
 
Index: /trunk/nv/stl/memory.hh
===================================================================
--- /trunk/nv/stl/memory.hh	(revision 406)
+++ /trunk/nv/stl/memory.hh	(revision 407)
@@ -36,15 +36,18 @@
 
 	template< typename T >
-	class storage_ref
+	class array_ref
 	{
 	public:
-		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;
-
+		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;
+		typedef value_type*                          iterator;
+		typedef const value_type*                    const_iterator;
+		typedef nv::reverse_iterator<iterator>       reverse_iterator;
+		typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
 
 		static constexpr bool is_static   = false;
@@ -52,7 +55,7 @@
 		static constexpr bool is_const    = false;
 
-		constexpr storage_ref() 
+		constexpr array_ref()
 			: m_data( nullptr ), m_size( 0 ) {}
-		constexpr storage_ref( value_type* a_data, size_type a_size )
+		constexpr array_ref( value_type* a_data, size_type a_size )
 			: m_data( a_data ), m_size( a_size ) {}
 
@@ -70,4 +73,29 @@
 		constexpr const char* raw_data() const { return reinterpret_cast<const char*>( m_data ); }
 		inline    char* raw_data() { return reinterpret_cast<char*>( m_data ); }
+
+		constexpr const_iterator begin() const { return const_iterator( m_data ); }
+		constexpr const_iterator end() const { return const_iterator( m_data + m_size ); }
+		inline    iterator begin() { return iterator( m_data ); }
+		inline    iterator end() { return iterator( m_data + m_size ); }
+		constexpr const_iterator cbegin() const { return const_iterator( m_data ); }
+		constexpr const_iterator cend() const { return const_iterator( m_data + m_size ); }
+		inline    reverse_iterator rbegin() { return reverse_iterator( end() ); }
+		inline    reverse_iterator rend() { return reverse_iterator( begin() ); }
+		constexpr const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }
+		constexpr const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
+		constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
+		constexpr const_reverse_iterator crend() const { return const_reverse_iterator( begin() ); }
+		inline    const_iterator iat( size_t i ) const { NV_ASSERT_ALWAYS( i <= m_size, "Index out of range" ); return begin() + i; }
+		inline    iterator       iat( size_t i ) { NV_ASSERT_ALWAYS( i <= m_size, "Index out of range" ); return begin() + i; }
+
+		inline reference       front() { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" );  return m_data[0]; }
+		inline const_reference front() const { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" ); return m_data[0]; }
+		inline reference       back() { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" ); return m_data[m_size - 1]; }
+		inline const_reference back() const { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" ); return m_data[m_size - 1]; }
+
+		reference operator[]( size_type i ) { NV_ASSERT_ALWAYS( i < m_size, "Out of range" ); return m_data[i]; }
+		const_reference operator[]( size_type i ) const { NV_ASSERT_ALWAYS( i < m_size, "Out of range" ); return m_data[i]; }
+		inline void fill( const value_type& value ) { fill_n( iterator( m_data ), iterator( m_data + m_size ), value ); }
+
 	protected:
 		value_type* m_data;
@@ -76,14 +104,18 @@
 
 	template< typename T >
-	class storage_view
+	class array_view
 	{
 	public:
-		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;
+		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;
+		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;
 
 		static constexpr bool is_static   = false;
@@ -91,9 +123,9 @@
 		static constexpr bool is_const    = true;
 
-		constexpr storage_view()
+		constexpr array_view()
 			: m_data( nullptr ), m_size( 0 ) {}
-		constexpr storage_view( const value_type* a_data, size_type a_size )
+		constexpr array_view( const value_type* a_data, size_type a_size )
 			: m_data( a_data ), m_size( a_size ) {}
-		constexpr storage_view( const storage_ref<T>& view )
+		constexpr array_view( const array_ref<T>& view )
 			: m_data( view.data() ), m_size( view.size() ) {}
 
@@ -109,4 +141,20 @@
 		constexpr size_type   raw_size() const { return sizeof( value_type ) * m_size; }
 		constexpr const char* raw_data() const { return reinterpret_cast<const char*>( m_data ); }
+
+		constexpr const_iterator begin() const { return const_iterator( m_data ); }
+		constexpr const_iterator end() const { return const_iterator( m_data + m_size ); }
+		constexpr const_iterator cbegin() const { return const_iterator( m_data ); }
+		constexpr const_iterator cend() const { return const_iterator( m_data + m_size ); }
+		constexpr const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }
+		constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
+		constexpr const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
+		constexpr const_reverse_iterator crend() const { return const_reverse_iterator( begin() ); }
+
+		inline const_reference front() const { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" ); return m_data[0]; }
+		inline const_reference back() const { NV_ASSERT_ALWAYS( !empty(), "front() called on empty data!" ); return m_data[m_size - 1]; }
+
+		inline const_iterator iat( size_t i ) const { NV_ASSERT_ALWAYS( i <= m_size, "Index out of range" ); return begin() + i; }
+		const_reference operator[]( size_type i ) const { NV_ASSERT_ALWAYS( i < m_size, "Out of range" ); return m_data[i]; }
+
 	protected:
 		const value_type* m_data;
@@ -161,4 +209,5 @@
 	{
 		object->~T();
+		NV_UNUSED( object ); // MSVC bug - if destructing basic type
 	}
 
@@ -489,11 +538,4 @@
 	}
 
-	template < typename T > 
-	using array_view    = detail::add_random_access< detail::add_iterators < storage_view< T > > >;
-	template < typename T >
-	using array_ref     = detail::add_random_access< detail::add_iterators < storage_ref< T > > >;
-	using mem_view      = array_view< char >;
-	using mem_ref       = array_ref< char >;
-
 }
 
Index: /trunk/nv/stl/string.hh
===================================================================
--- /trunk/nv/stl/string.hh	(revision 406)
+++ /trunk/nv/stl/string.hh	(revision 407)
@@ -35,8 +35,8 @@
 
 
-// 	short_string< size_t >
-// 	string32
-// 	string64
-// 	string
+	// 	short_string< size_t >
+	// 	string32
+	// 	string64
+	// 	string
 
 	template<>
@@ -63,6 +63,6 @@
 		{
 			typedef conditional_t < is_array<T>::value, remove_extent_t<T>*, remove_cv_t<T>	> decayed_type;
-			typedef bool_constant <	
-				is_same<       char *, decayed_type >::value ||	
+			typedef bool_constant <
+				is_same<       char *, decayed_type >::value ||
 				is_same< const char *, decayed_type >::value > type;
 		};
@@ -74,7 +74,7 @@
 	class string_view;
 
-// Stronger version
-//	template < typename T >
-//	struct is_string_base : is_template_base_of< T, string_base > {};
+	// Stronger version
+	//	template < typename T >
+	//	struct is_string_base : is_template_base_of< T, string_base > {};
 
 	template < typename T, typename Enable = void >
@@ -94,8 +94,8 @@
 	// string base class - will become a base for a string class later
 	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;
+	class string_base : public Storage
+	{
+		typedef Storage                                     base_type;
+		typedef string_base< base_type >                    this_type;
 	public:
 		typedef Storage                                     storage_type;
@@ -115,21 +115,10 @@
 
 		// conversion to std::string
- 		inline std::string to_string() const
- 		{
- 			return std::string( this->data(), this->size() );
- 		}
+		inline std::string to_string() const
+		{
+			return std::string( this->data(), this->size() );
+		}
 
 		inline size_type length()   const { return this->size(); }
-
-		// access
-		inline value_type operator[]( size_type i ) const { return this->data()[i]; }
-		inline value_type at( size_type i ) const
-		{
-			//	if ( i >= m_data ) NV_THROW( out_of_range( "string_ref::at" ) );
-			return this->data()[i];
-		}
-
-		inline value_type front()        const { return this->data()[0]; }
-		inline value_type back()         const { return this->data()[this->size() - 1]; }
 
 		// string operations
@@ -139,16 +128,16 @@
 		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;
+		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
@@ -163,4 +152,6 @@
 	protected:
 		using base_type::base_type;
+		constexpr string_base() : base_type() {}
+		constexpr string_base( pointer str, size_type len ) : base_type( str, len ) {}
 
 		template < typename ReverseIterator >
@@ -181,35 +172,21 @@
 	};
 
-	class string_view : public string_base< storage_view< char > >
+	class string_view : public string_base< array_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() )
-		{
-		}
+		typedef string_base< array_view< char > > this_type;
+
+		constexpr string_view() : this_type() {}
+		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 )
-		{
-		}
+		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() ) {}
+		constexpr string_view( const char* str, size_type len ) : this_type( str, len ) {}
 
 		// Literal constructors
 		template< size_t N >
-		inline string_view( char( &s )[N] ) : this_type( s, N - 1 ) {}
+		constexpr string_view( char( &s )[N] ) : this_type( s, N - 1 ) {}
 		template< size_t N >
-		inline string_view( const char( &s )[N] ) : this_type( s, N - 1 ) {}
+		constexpr string_view( const char( &s )[N] ) : this_type( s, N - 1 ) {}
 
 		// Non-literal constructors
@@ -256,7 +233,7 @@
 
 	template < typename Storage >
-	inline bool string_base< Storage >::starts_with( value_type c ) const 
-	{ 
-		return !this->empty() && c == this->front(); 
+	inline bool string_base< Storage >::starts_with( value_type c ) const
+	{
+		return !this->empty() && c == this->front();
 	}
 	template < typename Storage >
@@ -267,6 +244,6 @@
 
 	template < typename Storage >
-	inline bool string_base< Storage >::ends_with( value_type c ) const 
-	{ 
+	inline bool string_base< Storage >::ends_with( value_type c ) const
+	{
 		return !this->empty() && c == this->back();
 	}
@@ -323,5 +300,5 @@
 	{
 		return this->rfind( c );
-	} 
+	}
 	template < typename Storage >
 	inline auto string_base< Storage >::find_last_of( const string_view& s ) const -> size_type
@@ -423,10 +400,10 @@
 	}
 
-NV_STRING_BASE_CAST_OPERATORS( == )
-NV_STRING_BASE_CAST_OPERATORS( != )
-NV_STRING_BASE_CAST_OPERATORS( < )
-NV_STRING_BASE_CAST_OPERATORS( > )
-NV_STRING_BASE_CAST_OPERATORS( <= )
-NV_STRING_BASE_CAST_OPERATORS( >= )
+	NV_STRING_BASE_CAST_OPERATORS( == )
+		NV_STRING_BASE_CAST_OPERATORS( != )
+		NV_STRING_BASE_CAST_OPERATORS( < )
+		NV_STRING_BASE_CAST_OPERATORS( > )
+		NV_STRING_BASE_CAST_OPERATORS( <= )
+		NV_STRING_BASE_CAST_OPERATORS( >= )
 
 
@@ -447,5 +424,5 @@
 
 	// const string is movable but not copyable
-	class const_string : public string_base< storage_view< char > >
+	class const_string : public string_base< array_view< char > >
 	{
 	public:
@@ -479,5 +456,5 @@
 			size_type old_size = size();
 			assign( other.data(), other.size() );
-			other.assign( old_data , old_size );
+			other.assign( old_data, old_size );
 			return *this;
 		}
@@ -499,62 +476,135 @@
 	};
 
-	class literal_string : public string_base< storage_view< char > >
-	{
+	class literal_string : public string_base< array_view< char > >
+	{
+		constexpr literal_string( const char* str, size_t len ) : this_type( str, len ) {}
 	public:
-		typedef string_base< storage_view< char > > this_type;
-
-		// Literal constructors
+		typedef string_base< array_view< char > > this_type;
+		friend constexpr literal_string operator "" _ls( const char* str, size_t len );
+
 		template< size_t N >
-		inline literal_string( char( &s )[N] ) : this_type( s, N - 1 ) {}
+		constexpr 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 )
-{
-	size_t endpos = str.find_last_not_of( " \r\n\t" );
-	size_t startpos = str.find_first_not_of( " \r\n\t" );
-
-	if ( string_view::npos != endpos || string_view::npos != startpos )
-	{
-		if ( string_view::npos == startpos ) startpos = 0;
-		if ( string_view::npos != endpos )   endpos = endpos + 1 - startpos;
-		return str.substr( startpos, endpos );
-	}
-	return str;
+		constexpr literal_string( const char( &s )[N] ) : this_type( s, N - 1 ) {}
+	};
+
+	constexpr literal_string operator "" _ls( const char* str, size_t len )
+	{
+		return literal_string( str, len );
+	}
+
+	template < typename H >
+	class hashed_literal_string;
+	using hashed_literal_string_32 = hashed_literal_string< uint32 >;
+	using hashed_literal_string_64 = hashed_literal_string< uint64 >;
+
+	template < typename H >
+	class hashed_literal_string : public string_base< array_view< char > >
+	{
+		constexpr hashed_literal_string( const char* str, size_t len, H hash_code ) 
+			: this_type( str, len ), m_hash( hash_code ) {}
+	public:
+		typedef string_base< array_view< char > > this_type;
+
+		template< size_t N >
+		constexpr hashed_literal_string( char( &s )[N] )
+			: this_type( s, N - 1 ), m_hash( detail::fnv_hash<H>::hash( s, len-1 ) ) {}
+		template< size_t N >
+		constexpr hashed_literal_string( const char( &s )[N] )
+			: this_type( s, N - 1 ), m_hash( detail::fnv_hash<H>::hash( s, len - 1 ) ) {}
+
+		template < typename H2 >
+		constexpr H get_hash() const
+		{
+			static_assert( is_same< H, H2 >::value, "32/64 bit hash mismatch on hash_literal_string!" );
+			return m_hash;
+		}
+
+		friend constexpr hashed_literal_string_32 operator "" _hls32( const char* str, size_t len );
+		friend constexpr hashed_literal_string_64 operator "" _hls64( const char* str, size_t len );
+	protected:
+		H m_hash;
+	};
+
+	constexpr hashed_literal_string_32 operator "" _hls32( const char* str, size_t len )
+	{
+		return hashed_literal_string_32( str, len, detail::fnv_hash< uint32 >::hash( str, len ) );
+	}
+
+	constexpr hashed_literal_string_64 operator "" _hls64( const char* str, size_t len )
+	{
+		return hashed_literal_string_64( str, len, detail::fnv_hash< uint64 >::hash( str, len ) );
+	}
+
+	template< typename H >
+	struct hash< hashed_literal_string_32, H >
+	{
+		static_assert( is_same< uint32, H >::value, "hashed_literal_string_32 used with non-32 bit hash!" );
+		static constexpr H get( const hashed_literal_string_32& value )
+		{
+			return value.get_hash< H >();
+		}
+		constexpr H operator()( const hashed_literal_string_32& value ) const { return get( value ); }
+	};
+
+	template< typename H >
+	struct hash< hashed_literal_string_64, H >
+	{
+		static_assert( is_same< uint64, H >::value, "hashed_literal_string_64 used with non-64 bit hash!" );
+		static constexpr H get( const hashed_literal_string_64& value )
+		{
+			return value.get_hash< H >();
+		}
+		constexpr H operator()( const hashed_literal_string_64& value ) const { return get( value ); }
+	};
+
+	inline string_view trimmed( const string_view& str )
+	{
+		size_t endpos = str.find_last_not_of( " \r\n\t" );
+		size_t startpos = str.find_first_not_of( " \r\n\t" );
+
+		if ( string_view::npos != endpos || string_view::npos != startpos )
+		{
+			if ( string_view::npos == startpos ) startpos = 0;
+			if ( string_view::npos != endpos )   endpos = endpos + 1 - startpos;
+			return str.substr( startpos, endpos );
+		}
+		return str;
+	}
+
+	inline string_view rtrimmed( const string_view& str )
+	{
+		size_t endpos = str.find_last_not_of( " \r\n\t" );
+		if ( string_view::npos != endpos )
+		{
+			return str.substr( 0, endpos + 1 );
+		}
+		return str;
+	}
+
+	inline string_view ltrimmed( const string_view& str )
+	{
+		size_t startpos = str.find_first_not_of( " \r\n\t" );
+		if ( string_view::npos != startpos )
+		{
+			return str.substr( startpos );
+		}
+		return str;
+	}
+
+
+	inline string_view extract_extension( string_view filename )
+	{
+		size_t lastdot = filename.find_last_of( '.' );
+		if ( string_view::npos != lastdot )
+			return filename.substr( lastdot + 1 );
+		return filename;
+	}
+
 }
 
-inline string_view rtrimmed( const string_view& str )
-{
-	size_t endpos = str.find_last_not_of( " \r\n\t" );
-	if ( string_view::npos != endpos )
-	{
-		return str.substr( 0, endpos + 1 );
-	}
-	return str;
-}
-
-inline string_view ltrimmed( const string_view& str )
-{
-	size_t startpos = str.find_first_not_of( " \r\n\t" );
-	if ( string_view::npos != startpos )
-	{
-		return str.substr( startpos );
-	}
-	return str;
-}
-
-
-inline string_view extract_extension( string_view filename )
-{
-	size_t lastdot = filename.find_last_of( '.' );
-	if ( string_view::npos != lastdot )
-		return filename.substr( lastdot + 1 );
-	return filename;
-}
-
-
-}
+using nv::operator "" _ls;
+using nv::operator "" _hls32;
+using nv::operator "" _hls64;
 
 #endif // NV_STL_STRING_HH
