Index: trunk/nv/stl/algorithm.hh
===================================================================
--- trunk/nv/stl/algorithm.hh	(revision 445)
+++ trunk/nv/stl/algorithm.hh	(revision 446)
@@ -18,4 +18,5 @@
 #include <nv/stl/algorithm/copy.hh>
 #include <nv/stl/algorithm/fill.hh>
+#include <nv/stl/algorithm/heap.hh>
 #include <nv/stl/utility.hh>
 #include <nv/stl/iterator.hh>
Index: trunk/nv/stl/algorithm/heap.hh
===================================================================
--- trunk/nv/stl/algorithm/heap.hh	(revision 446)
+++ trunk/nv/stl/algorithm/heap.hh	(revision 446)
@@ -0,0 +1,194 @@
+// 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 heap.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief heap algorithms
+*/
+
+#ifndef NV_STL_ALGORITHM_HEAP_HH
+#define NV_STL_ALGORITHM_HEAP_HH
+
+#include <nv/stl/algorithm/common.hh>
+#include <nv/stl/utility/common.hh>
+#include <nv/stl/iterator.hh>
+
+namespace nv
+{
+	namespace detail
+	{
+		template< 
+			typename RandomAccessIterator,
+			typename DifferenceType,
+			typename T,
+			typename Predicate
+		>
+		inline void push_heap_impl( 
+			RandomAccessIterator first, 
+			DifferenceType pivot,
+			DifferenceType top,
+			T&& value, 
+			Predicate pred
+		)
+		{
+			for ( 
+				DifferenceType index = ( pivot - 1 ) / 2;
+				top < pivot && pred( *( first + index ), value );
+				index = ( pivot - 1 ) / 2 )
+			{
+				*( first + pivot ) = ::nv::move( *( first + index ) );
+				pivot = index;
+			}
+
+			*( first + pivot ) = ::nv::move( value );
+		}
+
+		template<
+			typename RandomAccessIterator,
+			typename DifferenceType,
+			typename T,
+			typename Predicate
+		>
+		inline void fix_heap(
+			RandomAccessIterator first,
+			DifferenceType pivot,
+			DifferenceType bottom,
+			T&& value,
+			Predicate pred
+		)
+		{
+			DifferenceType top = pivot;
+			DifferenceType index = 2 * pivot + 2;
+			for ( ; index < bottom; index = 2 * index + 2 )
+			{
+				if ( pred( *( first + index ), *( first + ( index - 1 ) ) ) ) --index;
+				*( first + pivot ) = ::nv::move( *( first + index ) );
+				pivot = index;
+			}
+			if ( index == bottom )
+			{
+				*( first + pivot ) = ::nv::move( *( first + (bottom - 1) ) );
+				pivot = bottom - 1;
+			}
+			push_heap_impl( first, pivot, top, ::nv::move( value ), pred );
+		}
+
+		template< 
+			typename RandomAccessIterator,
+			typename T,
+			typename Predicate
+		>
+		inline void pop_heap_impl( 
+			RandomAccessIterator first, 
+			RandomAccessIterator last,
+			RandomAccessIterator dest,
+			T&& value,
+			Predicate pred
+		)
+		{
+			*dest = ::nv::move( *first );
+			fix_heap( first, 0, last - first, ::nv::move( value ), pred );
+		}
+
+	}
+
+	template<
+		typename RandomAccessIterator,
+		typename Predicate
+	>
+	inline void push_heap( RandomAccessIterator first, RandomAccessIterator last, Predicate pred )
+	{
+		typedef iterator_traits< RandomAccessIterator > traits;
+		typedef typename traits::difference_type diff_type;
+		typedef typename traits::value_type value_type;
+		if ( first != last )
+		{
+			--last;
+			diff_type diff = last - first;
+			if ( diff > 0 )
+			{
+				value_type value = ::nv::move( *last );
+				detail::push_heap_impl( first, diff, 0, ::nv::move( value ), pred );
+			}
+		}
+	}
+
+	template< typename RandomAccessIterator >
+	inline void push_heap( RandomAccessIterator first, RandomAccessIterator last )
+	{
+		push_heap( first, last, less<>() );
+	}
+
+	template<
+		typename RandomAccessIterator,
+		typename Predicate
+	>
+	inline void pop_heap( RandomAccessIterator first, RandomAccessIterator last, Predicate pred )
+	{
+		typedef iterator_traits< RandomAccessIterator > traits;
+		typedef typename traits::value_type value_type;
+		if ( last - first >= 2 )
+		{
+			value_type value = ::nv::move( *(last - 1 ) );
+			detail::pop_heap_impl( first, last - 1, last - 1, ::nv::move( value ), pred );
+		}
+	}
+
+	template< typename RandomAccessIterator >
+	inline void pop_heap( RandomAccessIterator first, RandomAccessIterator last )
+	{
+		pop_heap( first, last, less<>() );
+	}
+
+	template<
+		typename RandomAccessIterator,
+		typename Predicate
+	>
+	inline void make_heap( RandomAccessIterator first, RandomAccessIterator last, Predicate pred )
+	{
+		typedef iterator_traits< RandomAccessIterator > traits;
+		typedef typename traits::difference_type diff_type;
+		typedef typename traits::value_type value_type;
+		diff_type bottom = last - first;
+		if ( bottom >= 2 )
+		{
+			for ( diff_type pivot = bottom / 2; 0 < pivot; )
+			{
+				--pivot;
+				value_type value = ::nv::move( *( first + pivot ) );
+				fix_heap( first, pivot, bottom, ::nv::move( value ), pred );
+			}
+		}
+	}
+
+	template< typename RandomAccessIterator >
+	inline void make_heap( RandomAccessIterator first, RandomAccessIterator last )
+	{
+		make_heap( first, last, less<>() );
+	}
+
+	template<
+		typename RandomAccessIterator,
+		typename Predicate
+	>
+	inline void sort_heap( RandomAccessIterator first, RandomAccessIterator last, Predicate pred )
+	{
+		for ( ; last - first >= 2; --last )
+		{
+			pop_heap( first, last, pred );
+		}
+	}
+
+	template< typename RandomAccessIterator >
+	inline void sort_heap( RandomAccessIterator first, RandomAccessIterator last )
+	{
+		sort_heap( first, last, less<>() );
+	}
+
+}
+
+#endif // NV_STL_ALGORITHM_HEAP_HH
Index: trunk/nv/stl/priority_queue.hh
===================================================================
--- trunk/nv/stl/priority_queue.hh	(revision 446)
+++ trunk/nv/stl/priority_queue.hh	(revision 446)
@@ -0,0 +1,139 @@
+// Copyright (C) 2014-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 priority_queue.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief priority queue adaptor
+*/
+
+#ifndef NV_STL_PRIORITY_QUEUE_HH
+#define NV_STL_PRIORITY_QUEUE_HH
+
+#include <nv/stl/vector.hh>
+
+namespace nv
+{
+
+	template < 
+		typename T,
+		typename Container = vector< T >,
+		typename Predicate = less< typename Container::value_type >
+	>
+	class priority_queue
+	{
+	public:
+		typedef priority_queue< T, Container, Predicate > this_type;
+		typedef Predicate                                 compare_type;
+		typedef Container                                 container_type;
+		typedef typename Container::value_type            value_type;
+		typedef typename Container::size_type             size_type;
+		typedef typename Container::reference             reference;
+		typedef typename Container::const_reference       const_reference;
+
+		priority_queue() {}
+		priority_queue( const this_type& ) = delete;
+		priority_queue( this_type&& other ) 
+			: m_data( ::nv::move( other.m_data ) )
+			, m_compare( ::nv::move( other.m_compare ) ) {}
+
+		this_type& operator=( const this_type& ) = delete;
+		this_type& operator=( this_type&& )
+		{
+			m_data    = ::nv::move( m_data );
+			m_compare = ::nv::move( m_compare );
+			return ( *this );
+		}
+
+		explicit priority_queue( const compare_type& pred ) : m_data(), m_compare( pred ) {}
+		explicit priority_queue( container_type&& container, const compare_type& pred = compare_type() )
+			: m_data( ::nv::move( container ) )
+			, m_compare( pred )
+		{
+			make_heap( m_data.begin(), m_data.end() );
+		}
+
+		template < typename InputIterator >
+		priority_queue( InputIterator first, InputIterator last )
+			: m_data( first, last )
+		{
+			make_heap( m_data.begin(), m_data.end() );
+		}
+
+		template < typename InputIterator >
+		priority_queue( InputIterator first, InputIterator last, const compare_type& pred )
+			: m_data( first, last ), m_compare( pred )
+		{
+			make_heap( m_data.begin(), m_data.end() );
+		}
+
+		void push( value_type&& value )
+		{
+			m_data.push_back( ::nv::move( value ) );
+			push_heap( m_data.begin(), m_data.end(), m_compare );
+		}
+
+		template< typename... Args >
+		void emplace( Args&&... args )
+		{
+			m_data.emplace_back( ::std::forward<Args>( args )... );
+			push_heap( m_data.begin(), m_data.end(), m_compare );
+		}
+
+		bool empty() const
+		{
+			return m_data.empty();
+		}
+
+		size_type size() const
+		{
+			return m_data.size();
+		}
+
+		const_reference top() const
+		{
+			return m_data.front();
+		}
+
+		void push( const value_type& value )
+		{
+			m_data.push_back( value );
+			push_heap( m_data.begin(), m_data.end(), m_compare );
+		}
+
+		void pop()
+		{
+			pop_heap( m_data.begin(), m_data.end(), m_compare );
+			m_data.pop_back();
+		}
+
+		void swap( this_type& rhs )
+		{
+			::nv::swap( m_data, rhs.m_data );
+			::nv::swap( m_compare, rhs.m_compare );
+		}
+
+	protected:
+		container_type m_data;
+		compare_type   m_compare;
+	};
+
+	template <
+		typename T,
+		typename Container,
+		typename Predicate
+	>
+	inline void swap(
+		priority_queue< T, Container, Predicate >& lhs,
+		priority_queue< T, Container, Predicate >& rhs
+	)
+	{
+		lhs.swap( rhs );
+	}
+
+}
+
+#endif // NV_STL_PRIORITY_QUEUE_HH
Index: trunk/nv/stl/type_traits/experimental.hh
===================================================================
--- trunk/nv/stl/type_traits/experimental.hh	(revision 445)
+++ trunk/nv/stl/type_traits/experimental.hh	(revision 446)
@@ -44,13 +44,10 @@
 #if NV_COMPILER == NV_MSVC
 #define NV_VOID_DECLTYPE( EXPR ) ::nv::match_ptr_t< &EXPR >
+#else
+#define NV_VOID_DECLTYPE( EXPR ) decltype( EXPR )
+#endif
 #define NV_GENERATE_HAS_MEMBER( MEMBER ) \
 template< typename, typename = nv::void_t<> > struct has_##MEMBER##_member : nv::false_type {}; \
 template< typename T > struct has_##MEMBER##_member <T, nv::void_t< NV_VOID_DECLTYPE( T::MEMBER ) > > : true_type{};
-#else
-#define NV_VOID_DECLTYPE( EXPR ) decltype( EXPR )
-#define NV_GENERATE_HAS_MEMBER( MEMBER ) \
-template< typename, typename = nv::void_t<> > struct has_##MEMBER##_member : nv::false_type {}; \
-template< typename T > struct has_##MEMBER##_member <T, nv::void_t< NV_VOID_DECLTYPE( T::MEMBER ) > > : true_type{};
-#endif
 
 namespace nv
