Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::extent on std::array

I have a templatized function and I want to static_assert that it's type has a size of three. This code illustrates what I'm trying to do, but doesn't work:

template < typename T >
void foo( T& param )
{
    // This line is the one that I need to figure out how to write
    static_assert( 3 == std::extent< T >::value, "param must have a size of 3" );
}

int main( void )
{
    int cArray[3];
    std::array< int, 3 > stdArray;

    foo( cArray );
    foo( stdArray );
}
like image 868
Jonathan Mee Avatar asked Mar 28 '14 12:03

Jonathan Mee


2 Answers

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.

like image 131
iavr Avatar answered Sep 29 '22 00:09

iavr


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" );
}
like image 41
Jonathan Mee Avatar answered Sep 29 '22 00:09

Jonathan Mee