First, how can make_shared support an array type of unknown size? I
would think the array size is required.
Boost uses a helper class to determine the return type of its shared_ptr::operator[](...)
. It also uses another helper class boost::detail::sp_extent
which provides specializations for array types to determine bounds (if T
can be decomposed to T[]
), Here is a summarized snippet from http://www.boost.org/doc/libs/1_63_0/boost/smart_ptr/shared_ptr.hpp :
namespace boost{
template<typename T>
class shared_ptr{
.....
typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
{
BOOST_ASSERT( px != 0 );
BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
}
....
}
namespace detail{
template< class T > struct sp_array_access
{ typedef void type; };
template< class T > struct sp_array_access< T[] >
{ typedef T & type; };
template< class T, std::size_t N > struct sp_array_access< T[N] >
{ typedef T & type; };
template< class T > struct sp_extent
{ enum _vt { value = 0 }; };
template< class T, std::size_t N > struct sp_extent< T[N] >
{ enum _vt { value = N }; };
}//end namepace detail
}//end namespace boost
Second, what is the difference between sh_arr2 and sh_arr3? Both seem
to be creating an array of int size 30.
The second includes range checking. From Boost docs:
Starting with Boost release 1.53, shared_ptr can be used to hold a
pointer to a dynamically allocated array. This is accomplished by
using an array type (T[] or T[N]) as the template parameter. There is
almost no difference between using an unsized array, T[], and a sized
array, T[N]; the latter just enables operator[] to perform a range
check on the index.