Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ equivalent of #define for integers

Tags:

c++

c++14

I am looking for a portable one line replacement for the #define in the following code. The replacement should hide the word APPLE in the namespace of the Foo object.

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

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

I tried to make this more C++ friendly this, and it worked using the Intel 2017 compiler:

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

// elsewhere

    Foo a(Foo::APPLE);

but it does not work with g++ ((GCC) 6.3.1 20170216), because it gives the error

undefined reference to Foo::APPLE

because it is probably trying to take a reference to APPLE.

I know I can "fix" the problem by creating definition in a *.cpp file of

constexpr int Foo::APPLE;

but that violates my ideal of having the #define be replaced by 1 line. My Foo class is header-file only, and now I would need a cpp file just for the definition of Foo::APPLE. I know I could also declare APPLE as a function (static constexpr int APPLE() {return 123;}) but that is a whole lot more typing in the declaration and at every point of use I need to call the function with ().

It seems easier just to use the #define and be done with it. Non-static const int works fine, but APPLE is not usable as an argument to the constructor. Maybe there is a good reason why this is impossible in C++.

Edit: This is not a duplicate of Undefined reference to static constexpr char[]. That question is related to a string and why the particular error message comes up. I am trying to avoid using static linkage all together (I acknowledge in my question that I am aware of how to do static linkage) and I want to do it a "better/cleaner" way, and I see from the Answers that the way that passes my criteria is to use enum.

like image 608
Mark Lakata Avatar asked Jan 28 '23 07:01

Mark Lakata


1 Answers

You've already listed most alternatives in your question. You'll need consider which approach you want to take:

  • Use inline variable which requires C++17 (your first attempt works implicitly in this standard)
  • Define the static member in a source file, which you don't want to do
  • Use an inline static member function instead, which you also don't want
  • Use a namespace scoped constexpr variable instead of a member
  • Use a member enum: enum : int { APPLE = 123 };
  • Use the macro (don't pick this)
like image 146
eerorika Avatar answered Jan 30 '23 11:01

eerorika