【问题标题】:Size of reference to std::array not available at compiletime对 std::array 的引用大小在编译时不可用
【发布时间】:2020-08-09 21:37:02
【问题描述】:

我很想知道为什么下面代码中的第二个static_assert 不起作用。看起来即使数组 c 是对 a 的引用,数组的大小也嵌入在类型中,因此它应该在编译时可用。

#include <array>

int main()
{
    std::array<int,2> a = {1,2};
    std::array<int,2> b = {2,3};
    std::array<int,2>& c = a;

    static_assert(a.size() == b.size(), "a.size==b.size"); // ok size of array is compile time constant
    static_assert(c.size() == a.size(), "c.size==a.size"); // compiler error "static_assert expression is not an integral constant expression"
}

【问题讨论】:

  • 这能回答你的问题吗:stackoverflow.com/questions/28614591/…
  • 因为a不是常量表达式
  • 我现在很感兴趣为什么std::declval&lt;decltype(c)&gt;().size() 可以与 MSVC 一起使用,但不能与 clang 或 gcc 一起使用。

标签: c++ arrays static-assert stdarray


【解决方案1】:

数组的大小嵌入在类型中,因此它应该在编译时可用。

这是真的。但无论如何,c 不是常量表达式,因此包含它作为子表达式的表达式不能是常量表达式 - 除了某些仅与操作数类型交互的运算符,例如 sizeof

例如,您可以使用以下方法获取尺寸:

static_assert(
    std::tuple_size<
        std::remove_reference_t<decltype(c)>
    >::value == a.size(),
    "c.size==a.size"
);

不幸的是,它不是很漂亮。

【讨论】:

  • 可能会将其包装到派生模板中。. Tuple_size 只不过是使用sizeof()integral_constant,所以直截了当的sizeof() 成语也可以,如果tuple_size 不是包含在实施中(有时会被忽略)。
【解决方案2】:

请注意,如果您将所有声明移出主函数,代码将编译。为什么?因为a 是自动变量,所以它不是真正的编译时对象,并且这里没有省略引用,因此acc.size() 都不是constexpr。对于全局变量a 的位置可以在编译时确定。

如果您尝试在这样的函数中绑定它们:

constexpr std::array<int,2> a = {1,2};
std::array<int,2> b = {2,3};
constexpr const std::array<int,2>& c = a;

你会得到a 不是常量表达式的错误。仍然可以编译的变体:

#include <array>

std::array<int,2> a = {1,2};
std::array<int,2> b = {2,3};

int main()
{
    std::array<int,2>& c = a;

    static_assert(a.size() == b.size(), "a.size==b.size"); 
    static_assert(c.size() == a.size(), "c.size==a.size"); 
}

【讨论】:

  • 这种行为只是为了表明 C++ 是多么的荒谬。
  • @PaulSanders Russel 的悖论听起来也很荒谬,但它是合乎逻辑的。我们已经为运行时创建的“某物”创建了运行时别名,但是我们使用函数sizeof() 调用对调用它的对象的性质敏感的函数询问有关编译时已知属性的问题。制定规则的方式是不合逻辑的,编译器必须如何预测我们询问它可以推断出的东西。
  • size(),不是sizeof(),这是一个错字
猜你喜欢
  • 1970-01-01
  • 2017-12-02
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
相关资源
最近更新 更多