条件编译(constexpr if)和“ISO C++禁止零大小数组”

ny6fqffe  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(222)

使用以下代码:

#include <algorithm>

constexpr int DATA_SIZE = 5;

constexpr int A_ARRAY_ALLOWED_SIZE = 5;
constexpr int A_ARRAY_SIZE = std::min(A_ARRAY_ALLOWED_SIZE, DATA_SIZE);
constexpr int B_ARRAY_SIZE = DATA_SIZE - A_ARRAY_ALLOWED_SIZE;

class A {
    int a[A_ARRAY_SIZE];
};

class B {
    int b[B_ARRAY_SIZE];
};

int main()
{
    A a;
    
    if constexpr (B_ARRAY_SIZE)
    {
        B b;
    }

    return 0;
}

我得到了编译器错误(带有-pedantic标志),它抱怨不允许零大小的数组。在我的例子中,没有创建零大小数组的对象,但看起来它仍然是一个问题。
我试图通过使用std::conditional来解决这个问题,但即使这样,我还是得到了一个额外的函数,如:

constexpr int Get_B_ARRAY_SIZE()
{
    if (B_ARRAY_SIZE)
        return B_ARRAY_SIZE;
    return 1; // workaround for zero-size array
}

怎样才是正确的处理方法呢?

    • EDIT:**我知道所有if分支都应该包含有效代码。我也知道零大小的数组是不允许的。我的问题是如何重构这段代码以获得类似于没有-pedantic标志编译时的行为。我怀疑我可以使用模板元编程来达到这个目的,但我不确定如何做到。
hgqdbh6s

hgqdbh6s1#

如果你需要std::conditional的等价物,但是是值,而不是类型,你可以这样做:

#include <iostream>
#include <type_traits>

template<size_t N>
struct safe_array_size : std::integral_constant<size_t, N> {};

template<>
struct safe_array_size<0> : std::integral_constant<size_t, 1> {};

int main()
{
    char a[safe_array_size<0>::value];
    char b[safe_array_size<1>::value];
    std::cout << sizeof(a) << std::endl;
    std::cout << sizeof(b) << std::endl;
}

或者使用std::conditional

#include <iostream>
#include <type_traits>

template<size_t N>
constexpr size_t safe_array_size = std::conditional_t<N==0, std::integral_constant<size_t, 1>, std::integral_constant<size_t, N>>::value;

int main()
{
    char a[safe_array_size<0>];
    char b[safe_array_size<1>];
    std::cout << sizeof(a) << std::endl;
    std::cout << sizeof(b) << std::endl;
}
uxhixvfz

uxhixvfz2#

if constexpr(至少,您是如何使用它的)不能直接解决这个错误,因为它是一个格式错误的类定义。您是否示例化这个类是无关紧要的。您可以通过使用std::max确保数组大小不为零来解决这个问题:

#include <algorithm>

constexpr int DATA_SIZE = 5;

constexpr int A_ARRAY_ALLOWED_SIZE = 5;
constexpr int A_ARRAY_SIZE = std::min(A_ARRAY_ALLOWED_SIZE, DATA_SIZE);
constexpr int B_ARRAY_SIZE = DATA_SIZE - A_ARRAY_ALLOWED_SIZE;

class A {
    int a[A_ARRAY_SIZE];
};

class B {
    int b[std::max(B_ARRAY_SIZE, 1)];
};

int main()
{
    A a;
    
    if constexpr (B_ARRAY_SIZE)
    {
        B b;
    }

    return 0;
}

请注意,std::maxC++14的constexpr。如果您使用C++11,则可以实现自己的max函数。
如果您需要确保类永远不会被示例化,除非数组大小为非零,那么上面代码中的if constexpr检查将处理这个问题。

相关问题