当ArrayCount是模板时,clang和gcc都无法编译下面的代码。这似乎是错误的,特别是考虑到SizeCount解决方案的sizeof工作。 ArrayCount的模板版本通常是一个更好的解决方案,但它在这里受到影响,并且constexpr似乎没有达到其承诺的精神。
#if 1
template<typename T, size_t N>
constexpr size_t ArrayCount(T (&)[N])
{
return N;
}
// Results in this (clang): error : static_assert expression is not an integral constant expression
// Results in this (gcc): error: non-constant condition for static assertion, 'this' is not a constant expression
#else
#define ArrayCount(t) (sizeof(t) / sizeof(t[0]))
// Succeeds
#endif
struct X
{
int x[4];
X() { static_assert(ArrayCount(x) == 4, "should never fail"); }
};
答案 0 :(得分:2)
正确的解决方案不使用自制程序代码,而是使用简单的类型特征:
int a[] = {1, 2, 3};
#include <type_traits>
static_assert(std::extent<decltype(a)>::value == 3, "You won't see this");
答案 1 :(得分:1)
我觉得这段代码无法编译,因为ArrayCount是一个非constexpr
参数的函数。根据标准,我认为这意味着ArrayCount
必须被证实为非constexpr
函数。
当然有解决方法。我可以想到两个头脑(一个用另一个实现):
template<typename T> struct ArrayCount;
template<typename T, size_t N>
struct ArrayCount<T[N]> {
static size_t const size = N;
};
template<typename T>
constexpr size_t ArrayCount2() {
return ArrayCount<T>::size;
}
struct X {
int x[4];
X() {
static_assert(ArrayCount<decltype(x)>::size == 4, "should never fail");
static_assert(ArrayCount2<decltype(x)>() == 4, "should never fail");
}
};
它确实意味着您可能不希望使用decltype()
,但它确实打破了采用非constexpr
参数的形式约束。