constexpr:为什么我的表达式不是常量表达式?

问题描述 投票:0回答:1

我想在编译时定义一些缓冲区并使用 static_assert 检查它们的大小:

struct  Buffer{
    int* array;
    size_t size;
};

template<typename T, int size>
struct ConstArray{
  T arr[size];

  constexpr ConstArray(T t[size]):arr(){
    for(int e = 0; e < size; e++)
      arr[e] = t[e];
  }

  constexpr const T& operator[](size_t e)const{
    return &arr[e];
  }
};

struct A {
    Buffer* b;
};

constexpr ConstArray<A, 1> a_maps(    
    (A[]){(Buffer[]){(int[]){0,1,2}, 3}} // error: constexpr variable 'a_maps' must be initialized by a constant expression 
);

int main()
{
    static_assert(a_maps[0].b->size == 3, "NOP"); // error: static assertion expression is not an integral constant expression
    return 0;
}

有什么建议可以使这种方法可行吗?

https://godbolt.org/z/W1xGd4n5b

c++ constexpr static-assert
1个回答
1
投票

(A[]){/*...*/}
(int[]){0,1,2}
和 不是有效的标准 C++ 语法。您的编译器仅支持它们作为名为“复合文字”的扩展,它来自 C。 因为标准对这种语法一无所知,所以争论你的代码是否应该是常量表达式几乎毫无意义。这完全取决于编译器。

在 C++ 代码中使用它们不是一个好主意,因为复合文字

看起来

类似于 C++ 中的T{...}语法,但在 C 中它们的行为实际上非常不同。它们具有不同的存储期限、生命周期和价值类别。因此,现在还不清楚 C++ 扩展的行为是否类似于 C 中的 C 语法,或者是否更类似于 C++ 结构。需要在编译器文档中进行验证,以免意外导致UB。

使用 

-pedantic-errors

进行编译,让 GCC 和 Clang 在 C++ 模式下抱怨此扩展(如果您只想警告,则使用

-pedantic
)。
    

© www.soinside.com 2019 - 2024. All rights reserved.