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

#include <utility>
#include <type_traits>
#include <iterator>
#include <cstdio>
#include <algorithm>
#include <compare>
#include <cstring>

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 >{} );
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值