等同于#define的整数的C ++

时间:2018-10-18 23:32:32

标签: c++ c++14

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

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

2 个答案:

答案 0 :(得分:6)

您已经在问题中列出了大多数替代方案。您需要考虑要采用的方法:

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

答案 1 :(得分:2)

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

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

您定义一个具有恒定静态数据成员的类模板,该成员的值就是您想要的值。您可以离线定义该静态数据成员-但在标头中,因为它是类模板的静态数据成员。在这种情况下,std::integral_constant已经做完了所有事情,因此您不必自己编写。

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