template<typename T, std::size_t N>
constexpr std::size_t countof( T const(&)[N] ) { return N; }
通过你的两个测试。无法将 a 转换int*
为 a T const(&)[N]
,因此不需要禁用代码。
要扩展它,我们应该添加:
template<typename T, std::size_t N>
constexpr std::size_t countof( std::array<T,N> const& ) { return N; }
我什至可能很想将其扩展到调用size()
容器。虽然它通常不是编译时的,但统一性可能很有用:
for(int i=0; i<countof(c); ++i) {
// code
}
或者你有什么。
template<typename T, std::size_t N>
constexpr std::size_t countof( T const(&)[N] ) { return N; }
template<typename T> struct type_sink { typedef void type; };
template<typename T> using TypeSink = typename type_sink<T>::type;
template<typename T, typename=void>
struct has_size : std::false_type {};
template<typename T>
struct has_size<T, TypeSink< decltype( std::declval<T>().size() ) > >:
std::true_type
{};
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b,T>::type;
template<typename T>
constexpr
EnableIf<has_size<T const&>::value,std::size_t>
countof( T const& t ) {
return t.size();
}
// This is optional. It returns `void`, because there
// is no need to pretend it returns `std::size_t`:
template<typename T>
constexpr
EnableIf<std::is_pointer<T>::value>
countof( T const& t ) = delete;
这非常冗长,但为我们提供了std::array
支持、std::initializer_list
支持、C 样式数组支持——所有这些都在编译时——并且在运行时标准容器和字符串都countof
可以。如果你传递一个指针,你会被告知你调用的函数是delete
ed。
在这种情况下,我尝试创建一个static_assert
,但遇到了任何template
必须具有有效专业化的解析规则的问题。我怀疑将整个问题路由到countof_impl
具有基于 SFINAE 的专业化的类中可能会解决该问题。
=delete
or解决方案的一个缺点static_assert
是指针实际上存在重载。如果你没有那个,那么根本就没有可以调用的有效函数接受一个指针:这更接近事实。