gpt4 book ai didi

c++ - 在非常量上下文中使用 std::size

转载 作者:行者123 更新时间:2023-12-01 14:05:59 24 4
gpt4 key购买 nike

我想知道为什么只有类型很重要时 constexpr 函数(特别是 std::size )在某些非常量上下文中不起作用。

让我们看一下两个 array_size 实现:

  • 老好 c++98
  • template <typename T, size_t N>
    char (&array_size_helper(const T (&)[N]))[N];
    #define array_size(a) sizeof(array_size_helper(a))
  • 从 C++11 开始,您可以使用 constexpr(以下是来自 GCC-8 的 std::size 实现)
  • constexpr size_t size(const _Tp (&/*__array*/)[_Nm]) noexcept { return _Nm; }

    第二个版本很好,很完美,只是它的工作方式与第一个不同。由于第一个宏与 sizeof 相关它只关心类型,而 constexpr功能是很复杂的事情。

    考虑一个例子:
    struct A
    {
    int a[10];
    };

    template <typename T, size_t N>
    char (&array_size_helper(const T (&)[N]))[N];

    # define array_size(a) sizeof(array_size_helper(a))

    int main()
    {
    A a;
    A* new_A = reinterpret_cast<A*>(&a);
    static_assert(array_size(a.a) == 10) // OK;
    static_assert(array_size(new_A->a) == 10); //OK
    static_assert(std::size(a.a) == 10); //OK
    static_assert(std::size(new_A->a) == 10); //error: the value of ‘new_A’ is not usable in a constant expression
    }

    这是为什么?为什么 std::size关心除类型之外的任何事情?不应该重新实现吗?

    最佳答案

    我写了一个whole blog post对这个。不,std::size不应该重新实现。

    两种实现之间有一个重要区别:array_size() ,一切都在未经评估的环境中。只有类型很重要,而不是任何特定值。 array_size()适用于任何 C 数组类型,不适用于其他类型。
    std::size()另一方面适用于所有范围。但它必须评估它的论点。当我们进行持续评估时,我们必须遵守一套严格的规则。其中之一是未定义的行为是格式错误的——编译器必须跟踪每一个这样的访问。因此,当您读取指针或引用时,编译器必须验证该读取是否有效。 std::size(a.a) 看起来很奇怪有效,但 std::size(new_A->a)没有,但考虑在这两种情况下必须发生的不同操作:

  • 对于 std::size(a.a) ,我们不必看a .成员访问只是一些偏移量。我们绑定(bind)了对它的引用(std::size 的参数),但是 size() 的实现从未真正阅读过该引用资料。所以即使 a它本身在常量表达式中是不可读的,我们实际上并没有对它进行任何读取 - 所以这只是工作。
  • 对于 std::size(new_A->a) , 我们要做的第一件事就是读取 new_A 的值为了执行该取消引用。但是new_A不是常量,所以我们无法在常量评估期间读取它的值,所以我们已经完成了。我们甚至不需要我们正在读取的值并不重要,我们只关心它在这种情况下的类型。

  • 这是目前的一个基本限制 - 因为静态大小的范围需要类型特征(或宏)才能将其大小作为常量表达式,而动态大小的范围则需要依赖 std::size() .

    关于c++ - 在非常量上下文中使用 std::size,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61935819/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com