【问题标题】:C++ equivalent of #define for integersC++ 等价于整数的#define
【发布时间】:2018-10-18 23:32:32
【问题描述】:

我正在寻找以下代码中#define 的便携式单行替换。替换应该在Foo 对象的命名空间中隐藏单词APPLE

class Foo {
public:
#define APPLE 123
    Foo(int a) : a_(a) { }
};

 // elsewhere in another file
    Foo f(APPLE);

我试图让它对 C++ 更友好,并且它使用 Intel 2017 编译器工作:

class Foo {
public:
    static constexpr int APPLE = 123;
    Foo(int a) : a_(a) { }
};

// elsewhere

    Foo a(Foo::APPLE);

但它对 g++ ((GCC) 6.3.1 20170216) 不起作用,因为它给出了错误

undefined reference to Foo::APPLE

因为它可能试图引用APPLE

我知道我可以通过在 *.cpp 文件中创建定义来“解决”问题

constexpr int Foo::APPLE;

但这违反了我将 #define 替换为 1 行的理想。我的Foo 类只是头文件,现在我需要一个cpp 文件来定义Foo::APPLE。我知道我也可以将 APPLE 声明为一个函数 (static constexpr int APPLE() {return 123;}),但这需要在声明中输入更多内容,并且在每个使用点我都需要使用 () 调用该函数。

使用#define 并完成它似乎更容易。非静态const int 工作正常,但APPLE 不能用作构造函数的参数。也许有一个很好的理由说明这在 C++ 中是不可能的。

编辑:这不是Undefined reference to static constexpr char[] 的副本。该问题与字符串以及出现特定错误消息的原因有关。我试图避免一起使用静态链接(我在我的问题中承认我知道如何进行静态链接)并且我想以一种“更好/更清洁”的方式来做,我从答案中看到了这种方式通过我的标准是使用enum

【问题讨论】:

  • 你会用 C++17 吗?出于这个原因,C++17 有内联变量。
  • C 风格? enum { APPLE = 123 };
  • @MarkLakata 那么不幸的是,枚举可能是您的最佳选择。不理想,但它有效。
  • static constexpr int APPLE = 123; 需要分配存储空间并占用空间。你可以拿APPLE的地址。请改用enum。它实际上是一个符号常量(但你不能获取它的地址)。

标签: c++ c++14


【解决方案1】:

您已经在问题中列出了大多数备选方案。您需要考虑要采用哪种方法:

  • 使用需要 C++17 的内联变量(您的第一次尝试隐含在本标准中)
  • 在源文件中定义静态成员,您不想这样做
  • 改用内联静态成员函数,您也不希望这样做
  • 使用命名空间范围的 constexpr 变量而不是成员
  • 使用成员枚举:enum : int { APPLE = 123 };
  • 使用宏(不要选这个)

【讨论】:

  • enum 方法是唯一适合我的方法。谢谢
【解决方案2】:

除了已经提到的,还有“穷人的内联变量”:

static constexpr const int& APPLE = std::integral_constant<int, 123>::value;

您定义了一个类模板,其中包含一个常量静态数据成员,其值就是您想要的值。您在外部定义该静态数据成员 - 但在标题中,因为它是类模板的静态数据成员。在这种情况下,std::integral_constant 已经完成了所有这些操作,因此您不必自己编写。

然后,您将实际的静态数据成员常量定义为对该类模板静态数据成员的 constexpr 引用;不需要外联定义,因为不可能使用由常量表达式初始化的引用。

【讨论】:

  • 感谢您的回答。我不知道integral_constant 的存在,并且模板存在这一事实不再帮助我喜欢C++。那是为了解决什么问题? (我知道它解决了这个问题,但这不会给优化器带来巨大的负担,以弄清楚 APPLE 可以被视为文字吗?
  • integral_constant 主要用于模板元编程,将编译时常量编码为类型。在这里使用它很方便,但它几乎不是它的预期用途。这是编译器应该没有什么问题的微不足道的常量传播。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-29
  • 2022-01-24
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
相关资源
最近更新 更多