diff --git a/alib2std/src/alib/ptr_array b/alib2std/src/alib/ptr_array
new file mode 100644
index 0000000000000000000000000000000000000000..810145250e2df9f441dbd8f384cf62408acbe897
--- /dev/null
+++ b/alib2std/src/alib/ptr_array
@@ -0,0 +1 @@
+#include <extensions/ptr_array.hpp>
diff --git a/alib2std/src/extensions/ptr_array.hpp b/alib2std/src/extensions/ptr_array.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b348fd9dc9a8beb231432a0bd0e72e11d1cbf
--- /dev/null
+++ b/alib2std/src/extensions/ptr_array.hpp
@@ -0,0 +1,352 @@
+/*
+ * ptr_array.hpp
+ *
+ * Created on: Feb 28, 2014
+ * Author: Jan Travnicek
+ */
+
+#ifndef __PTR_ARRAY_HPP_
+#define __PTR_ARRAY_HPP_
+
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include "array.hpp"
+#include "compare.hpp"
+#include "iterator.hpp"
+#include "clone.hpp"
+
+namespace ext {
+
+template < class T, std::size_t N >
+class ptr_array {
+	std::array < T *, N > m_data;
+
+public:
+
+	using value_type = T;
+
+	using size_type = std::size_t;
+	using diference_type = std::ptrdiff_t;
+
+	using reference = value_type &;
+	using const_reference = const value_type &;
+	using pointer = T *;
+	using const_pointer = T * const;
+
+	using iterator = dereferencing_iterator < typename std::array < T *, N >::iterator >;
+	using const_iterator = dereferencing_iterator < typename std::array < T *, N >::const_iterator >;
+
+	using reverse_iterator = dereferencing_iterator < typename std::array < T *, N >::reverse_iterator >;
+	using const_reverse_iterator = dereferencing_iterator < typename std::array < T *, N >::const_reverse_iterator >;
+
+	template < class ... Types >
+	ptr_array ( Types && ... args ) : m_data ( make_array ( ext::clone ( std::forward < Types > ( args ) ) ... ) ) {
+	}
+
+	ptr_array ( ) {
+		for ( size_type i = 0; i < N; ++ i )
+			m_data.at ( i ) = nullptr;
+	}
+
+	ptr_array ( const ptr_array& other ) {
+		for ( size_type i = 0; i < N; ++ i )
+			m_data.at ( i ) = ext::clone ( other.at ( i ) );
+	}
+
+	ptr_array ( ptr_array && other ) noexcept {
+		for ( size_type i = 0; i < N; ++ i )
+			m_data.at ( i ) = ext::clone ( std::move ( other.at ( i ) ) );
+	}
+
+	~ptr_array ( ) {
+		for ( size_type i = 0; i < N; ++ i )
+			delete m_data.at ( i );
+	}
+
+	ptr_array < T, N > & operator = ( const ptr_array < T, N > & other ) {
+		if ( this == & other )
+			return * this;
+
+		for ( size_type i = 0; i < N; ++ i ) {
+			delete m_data.at ( i );
+			m_data.at ( i ) = ext::clone ( other.at ( i ) );
+		}
+
+		return *this;
+	}
+
+	ptr_array < T, N > & operator = ( ptr_array < T, N > && other ) {
+		std::swap ( m_data, other.m_data );
+
+		return *this;
+	}
+
+	template < class R >
+	void fill ( const R & value ) {
+		for ( size_type i = 0; i < N; ++ i )
+			m_data.at ( i ) = ext::clone ( value );
+	}
+
+	reference at ( size_type index ) {
+		return * m_data.at ( index );
+	}
+
+	const_reference at ( size_type index ) const {
+		return * m_data.at ( index );
+	}
+
+	reference operator [ ] ( size_type index ) {
+		return * m_data [ index ];
+	}
+
+	const_reference operator [ ] ( size_type index ) const {
+		return * m_data [ index ];
+	}
+
+	reference front ( ) {
+		return * m_data.front ( );
+	}
+
+	const_reference front ( ) const {
+		return * m_data.front ( );
+	}
+
+	reference back ( ) {
+		return * m_data.back ( );
+	}
+
+	const_reference back ( ) const {
+		return * m_data.back ( );
+	}
+
+	bool null ( size_type index ) const {
+		return m_data.at ( index ) == NULL;
+	}
+
+	/* T * const * data ( ) noexcept {
+		return m_data.data ( );
+	}
+
+	T const * const * data ( ) const noexcept {
+		return m_data.data ( );
+	} */
+
+	iterator begin ( ) noexcept {
+		return dereferencer ( m_data.begin ( ) );
+	}
+
+	const_iterator begin ( ) const noexcept {
+		return dereferencer ( m_data.begin ( ) );
+	}
+
+	const_iterator cbegin ( ) const noexcept {
+		return dereferencer ( m_data.cbegin ( ) );
+	}
+
+	iterator end ( ) noexcept {
+		return dereferencer ( m_data.end ( ) );
+	}
+
+	const_iterator end ( ) const noexcept {
+		return dereferencer ( m_data.end ( ) );
+	}
+
+	const_iterator cend ( ) const noexcept {
+		return dereferencer ( m_data.cend ( ) );
+	}
+
+	reverse_iterator rbegin ( ) noexcept {
+		return dereferencer ( m_data.rbegin ( ) );
+	}
+
+	const_reverse_iterator rbegin ( ) const noexcept {
+		return dereferencer ( m_data.rbegin ( ) );
+	}
+
+	const_reverse_iterator crbegin ( ) const noexcept {
+		return dereferencer ( m_data.crbegin ( ) );
+	}
+
+	reverse_iterator rend ( ) noexcept {
+		return dereferencer ( m_data.rend ( ) );
+	}
+
+	const_reverse_iterator rend ( ) const noexcept {
+		return dereferencer ( m_data.rend ( ) );
+	}
+
+	const_reverse_iterator crend ( ) const noexcept {
+		return dereferencer ( m_data.crend ( ) );
+	}
+
+	bool empty ( ) const noexcept {
+		return m_data.empty ( );
+	}
+
+	size_type size ( ) const noexcept {
+		return m_data.size ( );
+	}
+
+	size_type max_size ( ) const noexcept {
+		return m_data.max_size ( );
+	}
+
+	void reserve ( size_type new_cap ) {
+		m_data.reserve ( new_cap );
+	}
+
+	size_type capacity ( ) const noexcept {
+		return m_data.capacity ( );
+	}
+
+	void shrink_to_fit ( ) {
+		m_data.shrink_to_fit ( );
+	}
+
+	template < class R >
+	iterator set ( const_iterator pos, R && value ) {
+		m_data.at ( std::distance ( cbegin ( ), pos ) ) = ext::clone ( std::forward < R > ( value ) );
+		return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) );
+	}
+
+	template < class R >
+	iterator set ( const_iterator pos, T * value ) {
+		m_data.at ( std::distance ( cbegin ( ), pos ) ) = value ;
+		return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) );
+	}
+
+	template < class R, class ... Args >
+	iterator emplace_set ( const_iterator pos, Args && ... args ) {
+		m_data.at ( std::distance ( cbegin ( ), pos ) ) = new R ( std::forward < Args > ( args ) ... ) ;
+		return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) );
+	}
+
+	void swap ( ptr_array & other ) {
+		swap ( this->m_data, other.m_data );
+	}
+
+	template < std::size_t I >
+	auto & get ( ) & {
+		return * std::get < I > ( m_data );
+	}
+
+	template < std::size_t I >
+	const auto & get ( ) const & {
+		return * std::get < I > ( m_data );
+	}
+
+	template < std::size_t I >
+	auto && get ( ) && {
+		return std::move ( * std::get < I > ( m_data ) );
+	}
+};
+
+} /* namespace ext */
+
+namespace std {
+
+template < class ... Ts >
+void swap ( ext::ptr_array < Ts ... > & first, ext::ptr_array < Ts ... > & second ) {
+	first.swap ( second );
+}
+
+template < std::size_t I, class Type, std::size_t N >
+auto & get ( ext::ptr_array < Type, N > & tpl ) {
+	return tpl.template get < I > ( );
+}
+
+template < std::size_t I, class Type, std::size_t N >
+const auto & get ( const ext::ptr_array < Type, N > & tpl ) {
+	return tpl.template get < I > ( );
+}
+
+template < std::size_t I, class Type, std::size_t N >
+auto && get ( ext::ptr_array < Type, N> && tpl ) {
+	return tpl.template get < I > ( );
+}
+
+} /* namespace std */
+
+namespace ext {
+
+template < class T, std::size_t N >
+std::ostream& operator<<(std::ostream& out, const ext::ptr_array < T, N > & ptr_array) {
+	out << "[";
+
+	bool first = true;
+	for(const T& item : ptr_array) {
+		if(!first) out << ", ";
+		first = false;
+		out << item;
+	}
+
+	out << "]";
+	return out;
+}
+
+template < class T, std::size_t N >
+struct compare < ext::ptr_array < T, N > > {
+	int operator()(const ext::ptr_array < T, N > & first, const ext::ptr_array < T, N > & second) const {
+		static compare<typename std::decay < T >::type > comp;
+		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
+			int res = comp(*iterF, *iterS);
+			if(res != 0) return res;
+		}
+		return 0;
+	}
+};
+
+template < class T, std::size_t N >
+std::string to_string ( const ext::ptr_array < T, N > & value ) {
+	std::stringstream ss;
+	ss << value;
+	return ss.str();
+}
+
+template < class T, std::size_t N >
+bool operator == ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	static compare < ptr_array < T, N > > comp;
+	return comp ( first, second ) == 0;
+}
+
+template < class T, std::size_t N >
+bool operator != ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	return ! ( first == second );
+}
+
+template < class T, std::size_t N >
+bool operator < ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	static compare < ptr_array < T, N > > comp;
+	return comp ( first, second ) < 0;
+}
+
+template < class T, std::size_t N >
+bool operator > ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	return second < first;
+}
+
+template < class T, std::size_t N >
+bool operator <= ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	return ! ( first > second );
+}
+
+template < class T, std::size_t N >
+bool operator >= ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) {
+	return ! ( first < second );
+}
+
+template < typename Base, typename ... Types >
+constexpr ptr_array < typename std::remove_reference < Base >::type , sizeof ... ( Types ) + 1 > make_ptr_array ( Base && first, Types && ... other ) {
+	return ptr_array < typename std::remove_reference < Base >::type, sizeof ... ( Types ) + 1 > ( std::forward < Base > ( first ), std::forward < Types > ( other ) ... );
+}
+
+template < typename Base >
+constexpr ptr_array < typename std::remove_reference < Base >::type, 0 > make_ptr_array ( ) {
+	return ptr_array < typename std::remove_reference < Base >::type, 0 > ( );
+}
+
+} /* namespace ext */
+
+#endif /* __PTR_ARRAY_HPP_ */
diff --git a/alib2std/test-src/extensions/PtrArrayTest.cpp b/alib2std/test-src/extensions/PtrArrayTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..120cede2336b4bf3e395ae701b8256b27c897c5d
--- /dev/null
+++ b/alib2std/test-src/extensions/PtrArrayTest.cpp
@@ -0,0 +1,43 @@
+#include "PtrArrayTest.h"
+#include <alib/ptr_array>
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PtrArrayTest, "bits" );
+CPPUNIT_TEST_SUITE_REGISTRATION( PtrArrayTest );
+
+void PtrArrayTest::setUp() {
+}
+
+void PtrArrayTest::tearDown() {
+}
+
+void PtrArrayTest::testProperties() {
+	ext::ptr_array < int, 4 > data = {1, 2, 3, 4};
+
+	std::cout << data [ 0 ] << std::endl;
+
+	CPPUNIT_ASSERT ( data [ 0 ] == 1 );
+	CPPUNIT_ASSERT ( data.size ( ) == 4 );
+	CPPUNIT_ASSERT ( data [ 3 ] == 4 );
+}
+
+void PtrArrayTest::testPolymorph() {
+	ext::ptr_array < Base, 4 > data = ext::make_ptr_array < Base > ( Child1 ( ), Child1 ( ), Child2 ( ), Child2 ( ) );
+
+	CPPUNIT_ASSERT ( data.size ( ) == 4 );
+
+	CPPUNIT_ASSERT ( data [ 0 ].type ( ) == PtrArrayTest::Type::CHILD1 );
+	CPPUNIT_ASSERT ( data [ 1 ].type ( ) == PtrArrayTest::Type::CHILD1 );
+	CPPUNIT_ASSERT ( data [ 2 ].type ( ) == PtrArrayTest::Type::CHILD2 );
+	CPPUNIT_ASSERT ( data [ 3 ].type ( ) == PtrArrayTest::Type::CHILD2 );
+
+	ext::ptr_array < Base, 4 >::const_iterator iter = data.cbegin ( );
+	CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD1 );
+	++ iter;
+	CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD1 );
+	++ iter;
+	CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD2 );
+	++ iter;
+	CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD2 );
+	++ iter;
+	CPPUNIT_ASSERT ( iter == data.cend ( ) );
+}
diff --git a/alib2std/test-src/extensions/PtrArrayTest.h b/alib2std/test-src/extensions/PtrArrayTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b6e330810a3f4795ed4832e0968ad3412c9d0c5
--- /dev/null
+++ b/alib2std/test-src/extensions/PtrArrayTest.h
@@ -0,0 +1,68 @@
+#ifndef PTR_ARRAY_TEST_H_
+#define PTR_ARRAY_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <alib/compare>
+
+class PtrArrayTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( PtrArrayTest );
+  CPPUNIT_TEST( testProperties );
+  CPPUNIT_TEST( testPolymorph );
+  CPPUNIT_TEST_SUITE_END();
+
+  enum class Type {
+    CHILD1,
+    CHILD2
+  };
+
+  class Base {
+  public:
+    virtual ~Base ( ) {
+    }
+
+    virtual Base * clone ( ) const = 0;
+    virtual Base * plunder ( ) && = 0;
+
+    virtual Type type ( ) const = 0;
+  };
+
+  class Child1 : public Base {
+  public:
+    virtual Base * clone ( ) const {
+      return new Child1 ( * this );
+    }
+
+    virtual Base * plunder ( ) && {
+      return new Child1 ( * this );
+    }
+
+    virtual Type type ( ) const {
+      return Type::CHILD1;
+    }
+  };
+
+  class Child2 : public Base {
+  public:
+    virtual Base * clone ( ) const {
+      return new Child2 ( * this );
+    }
+
+    virtual Base * plunder ( ) && {
+      return new Child2 ( * this );
+    }
+
+    virtual Type type ( ) const {
+      return Type::CHILD2;
+    }
+  };
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testProperties();
+  void testPolymorph();
+};
+
+#endif  // PTR_ARRAY_TEST_H_