Index: trunk/nv/stl/utility.hh
===================================================================
--- trunk/nv/stl/utility.hh	(revision 475)
+++ trunk/nv/stl/utility.hh	(revision 476)
@@ -16,4 +16,5 @@
 #include <nv/stl/utility/common.hh>
 #include <nv/stl/utility/pair.hh>
+#include <nv/stl/utility/compressed_pair.hh>
 #include <nv/stl/utility/make_pair.hh>
 
Index: trunk/nv/stl/utility/compressed_pair.hh
===================================================================
--- trunk/nv/stl/utility/compressed_pair.hh	(revision 476)
+++ trunk/nv/stl/utility/compressed_pair.hh	(revision 476)
@@ -0,0 +1,210 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+ * @file pair.hh
+ * @author Kornel Kisielewicz epyon@chaosforge.org
+ * @brief compressed pair library
+ */
+
+#ifndef NV_STL_UTILITY_COMPRESSED_PAIR_HH
+#define NV_STL_UTILITY_COMPRESSED_PAIR_HH
+
+#include <nv/stl/utility/common.hh>
+
+namespace nv
+{
+
+	namespace detail
+	{
+		template < typename T1, typename T2, bool T1Empty, bool T2Empty >
+		class compressed_pair_impl;
+
+		template < typename T1, typename T2 >
+		class compressed_pair_impl< T1, T2, false, false >
+		{
+			typedef compressed_pair_impl< T1, T2, false, false > this_type;
+			typedef T1 first_type;
+			typedef T2 second_type;
+
+			constexpr compressed_pair_impl() : m_first(), m_second() {}
+			constexpr compressed_pair_impl( const first_type& f, const second_type& s )
+				: m_first( f ), m_second( s ) {}
+
+			compressed_pair_impl( const compressed_pair_impl& ) = default;
+			compressed_pair_impl( compressed_pair_impl&& ) = default;
+
+			this_type& operator= ( this_type&& rhs )
+			{
+				m_first = ::nv::forward<first_type>( rhs.m_first );
+				m_second = ::nv::forward<second_type>( rhs.m_second );
+			}
+
+			this_type& operator= ( const this_type& rhs )
+			{
+				m_first = rhs.m_first;
+				m_second = rhs.m_second;
+			}
+
+			void swap( this_type& rhs )
+			{
+				if ( this != &rhs )
+				{
+					swap( m_first, rhs.m_first );
+					swap( m_second, rhs.m_second );
+				}
+			}
+
+			first_type&        first() { return m_first; }
+			const first_type&  first() const { return m_first; }
+
+			second_type&       second() { return m_second; }
+			const second_type& second() const { return m_second; }
+
+		private:
+			first_type  m_first;
+			second_type m_second;
+		};
+
+		template < typename T1, typename T2 >
+		class compressed_pair_impl< T1, T2, true, false >
+			: protected remove_cv_t< T1 >
+		{
+			typedef compressed_pair_impl< T1, T2, true, false > this_type;
+			typedef remove_cv_t< T1 > base_type;
+			typedef T1 first_type;
+			typedef T2 second_type;
+
+			constexpr compressed_pair_impl() : first_type(), m_second() {}
+			constexpr compressed_pair_impl( const first_type& f, const second_type& s )
+				: first_type( f ), m_second( s ) {}
+
+			compressed_pair_impl( const compressed_pair_impl& ) = default;
+			compressed_pair_impl( compressed_pair_impl&& ) = default;
+
+			this_type& operator= ( this_type&& rhs )
+			{
+				m_second = ::nv::forward<second_type>( rhs.m_second );
+			}
+
+			this_type& operator= ( const this_type& rhs )
+			{
+				m_second = rhs.m_second;
+			}
+
+			void swap( this_type& rhs )
+			{
+				if ( this != &rhs )
+				{
+					swap( m_second, rhs.m_second );
+				}
+			}
+
+			first_type&        first() { return *this; }
+			const first_type&  first() const { return *this; }
+
+			second_type&       second() { return m_second; }
+			const second_type& second() const { return m_second; }
+
+		private:
+			second_type m_second;
+		};
+
+		template < typename T1, typename T2, bool T1Empty >
+		class compressed_pair_impl< T1, T2, T1Empty, true >
+			: protected remove_cv_t< T2 >
+		{
+			typedef compressed_pair_impl< T1, T2, T1Empty, true > this_type;
+			typedef remove_cv_t< T2 > base_type;
+			typedef T1 first_type;
+			typedef T2 second_type;
+
+			constexpr compressed_pair_impl() : second_type(), m_first() {}
+			constexpr compressed_pair_impl( const first_type& f, const second_type& s )
+				: second_type( s ), m_first( f ) {}
+
+			compressed_pair_impl( const compressed_pair_impl& ) = default;
+			compressed_pair_impl( compressed_pair_impl&& ) = default;
+
+			this_type& operator= ( this_type&& rhs )
+			{
+				m_first = ::nv::forward<first_type>( rhs.m_first );
+			}
+
+			this_type& operator= ( const this_type& rhs )
+			{
+				m_first = rhs.m_first;
+			}
+
+			void swap( this_type& rhs )
+			{
+				if ( this != &rhs )
+				{
+					swap( m_first, rhs.m_first );
+				}
+			}
+
+			first_type&        first() { return m_first; }
+			const first_type&  first() const { return m_first; }
+
+			second_type&       second() { return *this; }
+			const second_type& second() const { return *this; }
+
+		private:
+			first_type  m_first;
+		};
+
+	}
+
+	template < typename T1, typename T2 >
+	using compressed_pair = detail::compressed_pair_impl< T1, T2, ::nv::is_empty<T1>::value, ::nv::is_empty<T2>::value >;
+
+	template < typename T1, typename T2 >
+	void swap( compressed_pair< T1, T2 >& lhs, compressed_pair< T1, T2 >& rhs )
+	{
+		lhs.swap( rhs );
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator== ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return lhs.first == rhs.first && lhs.second == rhs.second;
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator!= ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return !( lhs == rhs );
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator< ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return lhs.first < rhs.first || ( !( rhs.first < lhs.first ) && lhs.second < rhs.second );
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator> ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return ( rhs < lhs );
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator<= ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return !( rhs < lhs );
+	}
+
+	template < typename T1, typename T2 >
+	constexpr bool operator>= ( const compressed_pair< T1, T2 >& lhs, const compressed_pair< T1, T2 >& rhs )
+	{
+		return !( lhs < rhs );
+	}
+
+}
+
+#endif // NV_STL_UTILITY_COMPRESSED_PAIR_HH
+
Index: trunk/nv/stl/utility/pair.hh
===================================================================
--- trunk/nv/stl/utility/pair.hh	(revision 475)
+++ trunk/nv/stl/utility/pair.hh	(revision 476)
@@ -47,5 +47,5 @@
 		{
 			first = ::nv::forward<first_type>( rhs.first );
-			second = ::nv::forward<first_type>( rhs.second );
+			second = ::nv::forward<second_type>( rhs.second );
 		}
 
