constexpr模板函数不会将成员数组大小视为const表达式

时间:2013-06-06 23:00:44

标签: c++11 clang sizeof constexpr static-assert

当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"); }
};

2 个答案:

答案 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参数的形式约束。