#include <cstddef>
template<class T, std::size_t N>
std::size_t length_of( T(&)[N] ) {
return N;
}
- , .
++ 11:
#include <array>
template<class T, std::size_t N>
constexpr std::size_t size( T(&)[N] ) {
return N;
}
template<class T, std::size_t N>
constexpr std::size_t size( std::array<T,N> const& ) {
return N;
}
template<class C,class=void>
struct has_size : std::false_type {};
template<class>using void_t=void;
template<class C, void_t< decltype( std::declval<C&>().size() ) > >
struct has_size : std::true_type {};
template<bool b, class T=void>using enable_if_t=typename std::enable_if<b,T>::type;
template<class C, class=enable_if_t< has_size<C>::value, bool[1] >>
constexpr std::size_t size( C const& c ) {
return c.size();
}
template<class C, class=enable_if_t< !has_size<C>::value, bool[2] >>
constexpr std::size_t size( C const& c ) {
using std::begin; using std::end;
return end(c)-begin(c);
}
which probably goes too far. Please note that non-random access iterators in containers that are not sized will probably not be able to compile (since it is -usually not defined), which is similar to purpoes (we don’t want to accidentally do O (n) work).
source
share