Kno*_*abe 9 c++ arrays templates enable-if c++11
给定一个数组a,我想countof(a)将数组中的元素数作为编译时常量.如果我有一个指针p,我想countof(p)不编译.这似乎应该是(1)直截了当,(2)通常涵盖在SO中,但(1)我无法使它工作,并且(2)搜索SO没有发现任何东西.
这是我的尝试.
#include <cstddef>
#include <type_traits>
template<typename T, std::size_t n,
typename = typename std::enable_if<std::is_array<T>::value>::type>
constexpr std::size_t countof(T (&)[n]) { return n; }
template<typename T,
typename = typename std::enable_if<std::is_pointer<T>::value>::type>
void countof(T*) = delete;
int main()
{
int a[10];
auto asize = countof(a); // should compile
static_assert(countof(a) == 10,
"countof(a) != 10!");
int *p;
auto psize = countof(p); // shouldn't compile
}
Run Code Online (Sandbox Code Playgroud)
救命?
template<typename T, std::size_t N>
constexpr std::size_t countof( T const(&)[N] ) { return N; }
Run Code Online (Sandbox Code Playgroud)
通过两个测试.无法将int*a 转换为a T const(&)[N],因此不需要禁用代码.
要扩展它,我们应该添加:
template<typename T, std::size_t N>
constexpr std::size_t countof( std::array<T,N> const& ) { return N; }
Run Code Online (Sandbox Code Playgroud)
我甚至可能想把它扩展到调用size()容器.虽然它通常不是编译时,但统一性可能有用:
for(int i=0; i<countof(c); ++i) {
// code
}
Run Code Online (Sandbox Code Playgroud)
或者你有什么.
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;
Run Code Online (Sandbox Code Playgroud)
这是非常冗长,但给我们std::array支持,std::initializer_list支持,C风格的数组支持 - 所有在编译时 - 并在运行时标准容器和字符串都countof能够.如果您传递指针,则会告诉您所调用的函数是deleteed.
我尝试static_assert在这种情况下创建一个,但遇到了解决规则的问题,任何template必须具有有效的专业化.我怀疑将整个问题路由到countof_impl基于SFINAE的专业化的类可能会解决这个问题.
一个缺点到=delete或static_assert解决方案是,在过载实际上存在指针.如果你没有那个,那么就没有一个有效的函数可以调用一个指针:这更接近事实.
| 归档时间: |
|
| 查看次数: |
711 次 |
| 最近记录: |