【c++11 std::array 简单实现】

#include 
#include 
#include 
#include 
#include 
#include 
#include 

template < typename _Tp, ::std::size_t _Nm >
struct __array_traits{
	typedef _Tp _Type[ _Nm ];
	typedef ::std::is_swappable< _Tp > _IS_Swappable;
	typedef ::std::is_nothrow_swappable< _Tp > _IS_Nothrow_Swappable;
	
	static constexpr _Tp&
	_S_ref( const _Type& __t, ::std::size_t __n ) noexcept
	{ return const_cast< _Tp& >( __t[__n] ); }
	static constexpr _Tp*
	_S_ptr( const _Type& __t ) noexcept
	{ return const_cast< _Tp* >( __t); }
};

template < typename _Tp >
struct __array_traits< _Tp, 0 >{
	struct _Type { };
	typedef ::std::true_type _IS_Swappable;
	typedef ::std::true_type _IS_Nothrow_Swappable;
	
	static constexpr _Tp&
	_S_ref( const _Type&, std::size_t ) noexcept
	{ return *static_cast< _Tp* >( nullptr ); }
	
	static constexpr _Tp*
	_S_ptr( const _Type& ) noexcept
	{ return nullptr; }
};

template < typename _Tp, ::std::size_t _Nm >
struct array{
	typedef _Tp  value_type;
	typedef ::std::add_pointer< ::std::decay_t< value_type > > pointer;
	typedef ::std::add_const< pointer > const_pointer;
	typedef ::std::add_lvalue_reference< ::std::decay_t < value_type > > reference;
	typedef ::std::add_const< reference > const_reference;
	typedef pointer iterator;
	typedef const_pointer const_iterator;
	typedef ::std::size_t size_type;
	typedef ::std::ptrdiff_t difference;
	typedef ::std::reverse_iterator< iterator > reverse_iterator;
	typedef ::std::reverse_iterator< const_iterator > const_reverse_iterator;
	typedef __array_traits< _Tp, _Nm > _AT_Type;
	typename _AT_Type::_Type _M_elems;
	constexpr pointer
	data( void ) noexcept
	{ return _AT_Type::_S_ptr( _M_elems ); }
	constexpr const_pointer
	data( void ) const noexcept
	{ return _AT_Type::_S_ptr( _M_elems ); }
	constexpr size_type
	size( void ) const noexcept
	{ return _Nm; }
	constexpr size_type
	max_size( void ) const noexcept
	{ return _Nm; }
	constexpr bool
	empty( void ) const noexcept
	{ return ! size(); }
	constexpr reference
	operator[]( size_type __n ) noexcept
	{ return _AT_Type::_S_ref( _M_elems, __n ); }
	constexpr const_reference
	operator[]( size_type __n ) const noexcept
	{ return _AT_Type::_S_ref( _M_elems, __n ); }
	constexpr reference
	at( size_type __n ){
		if( __n >= _Nm ){
			char _MsgBuf[ 64 ];
			sprintf( _MsgBuf,
			"array::at:: __n(which is %llu)"
			">= _Nm (which is %llu)",
			 __n, _Nm );
			throw ::std::out_of_range( _MsgBuf );
		}
		return _AT_Type::_S_ref( _M_elems, __n );
	}
	constexpr const_reference
	at( size_type __n ) const{
		return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
			  : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
							       ">= _Nm (which is %zu)"),
							   __n, _Nm),
			     _AT_Type::_S_ref(_M_elems, 0));
	}
	
	constexpr iterator
	begin( void ) noexcept
	{ return iterator( data() ); }
	constexpr const_iterator
	begin( void ) const noexcept
	{ return const_iterator( data() ); }
	constexpr iterator
	end( void ) noexcept
	{ return iterator( data() + _Nm ); }
	constexpr const_iterator
	end( void ) const noexcept
	{ return const_iterator( data() + _Nm ); }
	constexpr void
	fill( const value_type& __u )
	{ ::std::fill_n( begin(), size(), __u); }
	constexpr void
	swap( array& __other )
	noexcept( _AT_Type::_IS_Nothrow_Swappable::value )
	{ ::std::swap_ranges( begin(), end(), __other.begin(), __other.end() ); }
	constexpr reference
	front( void ) noexcept
	{ return *begin(); }
	constexpr const_reference
	front( void ) const noexcept
	{ return _AT_Type::_S_ref( _M_elems, 0 ); }
	constexpr reference
	back( void ) noexcept
	{ return _Nm ? *( end() - 1 ) : *end(); }
	constexpr const_reference
	back( void ) const noexcept{
		return _Nm ? _AT_Type::_S_ref( _M_elems, _Nm - 1)
				:  _AT_Type::_S_ref(_M_elems,0); }
};

template < typename _Tp, typename... _Up >
	array( _Tp,_Up... )
		->array< ::std::enable_if< ( ::std::is_same_v< _Tp, _Up >&& ...), _Tp>,
		sizeof...(_Up) + 1>;

template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator==( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two)
{ return ::std::equal( __one.begin(), __one.end(), __two.begin() ); }

template < typename _Tp, ::std::size_t _Nm >
constexpr ::std::partial_ordering
operator<=>( const array< _Tp, _Nm >& __one,
		     const array< _Tp, _Nm >& __two){
	if constexpr ( _Nm )
		return ::std::memcmp( __one.data(),
							  __two.data(),
							  _Nm * sizeof( _Tp ) )
		<=> 0;
	for( ::std::size_t __i { 0 }; __i < _Nm; ++__i ){
		auto __result = __one[__i] <=> __two[__i];
		if(  __result != 0 ) return __result;
	}
	return ::std::strong_ordering::equal;
}

template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator!=( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two )
		    { return !( __one == __two ); }

template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator<( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two)
		    { return ( __one <=> __two ) < 0; }


template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator>( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two)
		    { return __two < __one; }

template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator<=( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two)
		    { return !( __one > __two); }
		    
template < typename _Tp, ::std::size_t _Nm >
constexpr inline bool
operator>=( const array< _Tp, _Nm >& __one,
		    const array< _Tp, _Nm >& __two)
		    { return !( __one < __two); }

template < typename _Tp, ::std::size_t _Nm >
constexpr inline
typename ::std::enable_if<
	__array_traits< _Tp, _Nm >::_IS_Swappable::value
	>::type
	swap( array< _Tp, _Nm >& __one,
		  array< _Tp, _Nm >& __two)
		  noexcept( noexcept( __one.swap( __two ) ) )
		  { __one.swap(__two); }

template < typename _Tp, ::std::size_t _Nm >
constexpr inline
typename ::std::enable_if<
	!__array_traits< _Tp, _Nm >::_IS_Swappable::value
	>::type
	swap( array< _Tp, _Nm >& __one,
		  array< _Tp, _Nm >& __two) = delete;

template < ::std::size_t _INT,
			typename _Tp, ::std::size_t _Nm >
constexpr _Tp&
get( array< _Tp, _Nm >& __arr ) noexcept{
	static_assert( _INT < _Nm, " array index is within bounds" );
	return __array_traits< _Tp, _Nm >::_S_ref( __arr._M_elems, _INT );
}

template < ::std::size_t _INT,
			typename _Tp, ::std::size_t _Nm >
constexpr _Tp&&
get( array< _Tp, _Nm >& __arr ) noexcept{
	static_assert( _INT < _Nm, " array index is within bounds" );
	return ::std::move( get< _INT >( __arr ) );
}

template < ::std::size_t _INT,
			typename _Tp, ::std::size_t _Nm >
constexpr const _Tp&
get( array< _Tp, _Nm >& __arr ) noexcept{
	static_assert( _INT < _Nm, " array index is within bounds" );
	return __array_traits< _Tp, _Nm >::_S_ref( __arr._M_elems, _INT );
}

template < ::std::size_t _INT,
			typename _Tp, ::std::size_t _Nm >
constexpr const _Tp&&
get( array< _Tp, _Nm >& __arr ) noexcept{
	static_assert( _INT < _Nm, " array index is within bounds" );
	return ::std::move( get< _INT >( __arr ) );
}

template < bool _Move = false, typename _Tp, ::std::size_t... _Idx >
constexpr array< ::std::remove_cv_t< _Tp >, sizeof...( _Idx ) >
__to_array( _Tp (&__a)[sizeof...(_Idx)], ::std::index_sequence< _Idx... > ){
	if constexpr ( _Move )
		return {{::std::move( __a[ _Idx ] )...} };
	else
		return {{ __a[ _Idx ]...} };
}

template < typename _Tp, ::std::size_t _Nm >
constexpr array<::std::remove_cv_t< _Tp >, _Nm >
to_array( _Tp (&__a)[ _Nm ] )
noexcept( ::std::is_nothrow_constructible_v< _Tp, _Tp& > ){
	static_assert( !::std::is_array_v< _Tp > );
	static_assert( ::std::is_constructible_v< _Tp, _Tp& > );
	if constexpr (::std::is_constructible_v< _Tp, _Tp& >)
		return __to_array( __a, ::std::make_index_sequence< _Nm >{} );
}

template < typename _Tp, ::std::size_t _Nm >
constexpr array<::std::remove_cv_t< _Tp >, _Nm >
to_array( _Tp (&&__a)[ _Nm ] )
noexcept( ::std::is_nothrow_move_constructible_v< _Tp > ){
	static_assert( !::std::is_array_v< _Tp > );
	static_assert( ::std::is_move_constructible_v< _Tp > );
	if constexpr (::std::is_move_constructible_v< _Tp >)
		return __to_array< 1 >( __a, ::std::make_index_sequence< _Nm >{} );
}

你可能感兴趣的:(ADT数据结构实现,设计模式,语言特性,Modern,Cpp,c++,算法,开发语言,设计模式,数据结构)