【问题标题】:Can span be constexpr?span 可以是 constexpr 吗?
【发布时间】:2020-03-16 15:07:00
【问题描述】:

std::span 的所有构造函数都声明为 constexpr,但是我似乎无法让它们中的任何一个在 constexpr 上下文中工作。取消注释下面的任何 constexpr 都会导致编译错误。

#include <array>
#include <span>

int main()
{
    constexpr int carray[3] = { 0, 1, 2 };
    constexpr std::array<int, 3> array{ 0, 1, 2 };
    using S = std::span<const int, 3>;

    /*constexpr*/ S span1{ array.data(), 3 };
    /*constexpr*/ S span2{array.begin(), array.end()};
    /*constexpr*/ S span3{carray};
    /*constexpr*/ S span4{array};
}

实际上是否有可能创建一个 constexpr 跨度类型,因为当构造函数必须初始化指针或引用时,它们似乎永远无法在编译时进行评估?

【问题讨论】:

  • 取消注释 constexprs 不要删除它们。
  • 您正在初始化一个运行时跨度,我的意思是初始化一个 constexpr 跨度
  • 多哈。不知道我为什么这样做。没关系
  • 奇怪,不明白为什么有必要跨度只存在于本地范围内......

标签: c++ constexpr c++20


【解决方案1】:

您不能在这样的常量表达式中使用非静态函数局部变量。您需要地址稳定性,而这只能通过静态对象来实现。修改代码为

constexpr std::array<int, 3> array{ 0, 1, 2 };
constexpr int carray[3] = { 0, 1, 2 };

int main()
{
    using S = std::span<const int, 3>;

    constexpr S span1{ array.data(), 3 };
    constexpr S span2{array.begin(), array.end()};
    constexpr S span3{carray};
    constexpr S span4{array};
}

int main()
{
    static constexpr std::array<int, 3> array{ 0, 1, 2 };
    static constexpr int carray[3] = { 0, 1, 2 };
    using S = std::span<const int, 3>;

    constexpr S span1{ array.data(), 3 };
    constexpr S span2{array.begin(), array.end()};
    constexpr S span3{carray};
    constexpr S span4{array};
}

允许您创建constexpr std::span

【讨论】:

  • 范围不是问题。存储期限是。静态本地应该可以工作。
  • 如果所有对象都是 constexpr 函数中的函数本地对象(没有明确的 static),它也可以工作。此类对象是否具有默认的静态存储持续时间,还是有什么不同?
  • @n314159 我不确定这是否被允许,或者您是否陷入了可怕的境地:如果 constexpr 函数没有特化是核心常量表达式,则该函数格式错误,无法诊断必需的子句。 [expr.const]/10 只允许静态变量。
  • @n314159:我不确定你说的是什么有效(或“有效”),但请注意将某物用作常量表达式 in之间的区别> 一个函数(constexpr 或否)并使用某些东西构造一个常量表达式通过一个 constexpr 函数。
  • 您可能想说非静态(常量)可用于常量表达式,但不能用于它们的地址
猜你喜欢
  • 1970-01-01
  • 2012-02-23
  • 2015-05-07
  • 2015-11-30
  • 2020-12-17
  • 1970-01-01
  • 2021-04-18
  • 2012-12-25
  • 1970-01-01
相关资源
最近更新 更多