Using std::extent on std::array

亡梦爱人 提交于 2019-12-01 06:42:42

std::extent is defined for built-in arrays. For std::array use std::tuple_size instead. I don't know some trait that works on both, but it's easy to write one:

template<typename T>
struct array_size : std::extent<T> { };

template<typename T, size_t N>
struct array_size<std::array<T,N> > : std::tuple_size<std::array<T,N> > { };

and here's your foo, corrected/generalized (live example):

template < typename T >
void foo( T&& param )
{
    using U = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
    static_assert( 3 == array_size<U>::value, "param must have a size of 3" );
}

Prefer a universal reference T&& param, otherwise only lvalues can be used.

Jonathan Mee

This builds on iavr's solution.

template < typename T >
void foo( T& param )
{
    static_assert( 3 == ( std::is_array< T >::value ? std::extent< T >::value : std::tuple_size< T >::value ), "param must have a size of 3" );
}

I can't think of a way to write a single function that handles both, but this is what overloading is for.

template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( T (&)[Bound] )
{
    static_assert(Bound == N, "incorrect array size");
}

template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( const std::array<T,Bound>& )
{
    static_assert(Bound == N, "incorrect array size");
}

template <std::size_t N>
void check_array_size( ... )
{
    static_assert(N<0, "argument is not an array");
}

template <typename T>
void foo(T& param)
{
    check_array_size<3>(param);
    // actual function implementation...
}

I suspect you're having this error because at compile time (which is when *static_assert* is evaluated) the dimensions of cArray and stdArray are unknown, and std::extent returns zero:

http://en.cppreference.com/w/cpp/types/extent

In fact, the error disappears if you change the condition to equal to zero:

static_assert( std::extent< T >::value == 0, "param is not zero" );

Nevertheless, as it has already been pointed out in other posts, std::extent won't work for std::array, only for built in arrays such as cArray

AFTER OP's EDIT: Now that you have modified foo to accept a reference, you'll have that std::extent reports 3 for cArray and 0 (zero) for stdArray. Hence, you'll carry on having the exception at compile time, because the dimension of stdArray is not 3.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!