【问题标题】:Inline constexpr and anonymous namespace variables?内联 constexpr 和匿名命名空间变量?
【发布时间】:2021-02-04 07:17:52
【问题描述】:

我有以下问题。在 .hpp 文件中,我有一个必须使用命名空间全局变量的函数 Space::foo(),我想将其隐藏在匿名命名空间中。但现在我想知道,我是否会冒险在每个翻译单元中定义 values 并使用多个副本,或者只有一个?感谢您的帮助。这是因为我需要 Space 命名空间中的一堆函数以及一种私有数据部分(匿名命名空间的东西),因此 Space 有点像一个只有静态成员的类,但我不如果我将 .hpp 文件包含在不同的单元中,则不希望拥有这些变量的多个副本。

// .hpp file
#include <array>

namespace Space {
namespace {
  constexpr std::array<int, 10000> fill() { /* ... */ };
  inline constexpr std::array<int, 10000> values = fill();
}
  inline int foo(int i) {
    return values[i];
  }
}

【问题讨论】:

  • 是的,对不起。如果我不清楚我只想在我的程序中有一个值的实例,它在编译时预先计算,然后在运行时通过 Space::foo 访问。

标签: c++ inline constexpr c++20 linkage


【解决方案1】:

我是否有在每个翻译单元中定义多个副本的风险

是的。您将在每个 TU 中定义一个 values。您也不能将其声明为 extern constexpr,因为 [dcl.constexpr]/1 表示“constexpr 说明符应仅应用于变量的定义”。

由于目的似乎是能够选择恒定的值已评估,因此您可以同时创建 fillfoo consteval 并跳过 &lt;anonymous&gt;::values

namespace Space {
    namespace {
        consteval std::array<int, 10000> fill() {
            return {}; // replace with your filling algorithm
        };
    }

    inline consteval int foo(size_t i) {
        return fill()[i];
    }

    inline consteval int bar(size_t i, size_t j) {
        constexpr auto values = fill();
        return values[i] + values[j];
    }
}

这将使foo 和任何其他consteval 函数可以在fill() 中使用算法并在constexpr/consteval 情况下使用结果。

constexpr auto x = Space::bar(10, 20);

【讨论】:

  • 非常感谢,但是如果我改为将 Space 设为一个具有私有静态值和填充和公共静态 foo 的类,所有这些都在类中定义(也许我也删除了构造函数),我会有多个“值”,如果我在不同的 TU 中包含此类 .hpp 文件?直观地说,一个静态成员在整个程序中应该只存在一次,对吧?这样我仍然可以做 Space::foo 但值只存在于内存中的某个地方。我想我可以用命名空间来模仿这种行为,我会试着理解 consteval 的建议。
  • @lucmobz 是的,您可以这样做(但您不需要为此开设课程)。您需要声明它extern const ... values; 并将其填写到.cpp 文件中。然而,这意味着该数组很可能会被物化,即使它不需要。在上面的例子中,编译器可以优化掉数组,只返回values[10] + values[20] 的评估结果。该数组甚至不必存在于可执行文件或运行时中。
  • 我在 .hpp 文件命名空间 ns { inline constexpr int val = 10;实际上不会在多个 TU 中创建 val 的副本(在 c++17 中)。那么我的问题是否仅源于使用未命名的命名空间?我可以摆脱它(或称它为 detail),无论有多少 TU,数组值在整个代码中只会存在一次?
  • @lucmobz 是的,或者您可以将其放在命名空间中(detail 很流行):example
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
相关资源
最近更新 更多