0

当 ArrayCount 是模板时,clang 和 gcc 都无法编译下面的代码。这似乎是错误的,特别是考虑到 sizeof ArrayCount 解决方案有效的事实。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"); }
};
4

2 回答 2

2

正确的解决方案不使用自制代码,而是使用简单的类型特征:

int a[] = {1, 2, 3};

#include <type_traits>

static_assert(std::extent<decltype(a)>::value == 3, "You won't see this");
于 2013-06-07T00:01:12.470 回答
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参数的形式约束。

于 2013-06-06T23:25:03.730 回答