Author Topic: Help adding a static, compile time constant variable to a class/struct in C++  (Read 7117 times)

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
I’m trying to add a private variable to a class that is constant at compile time and static (does not reside in an individual instance of the class.)

Unfortunately, I cannot get my code to compile. Below is roughly what I’m typing in.
 
Code: [Select]
class XFile
{

...

private:
constexpr static string notSupportedMessage("Operating system not supported.");
};
I’m getting error code E0079 Expected a Type Specifier.

I was hoping for some insight in how to properly format the code.

-Brett


Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
String isn't a built-in type, so I don't think you can do what you're trying to do.  You can probably declare it as static and then define it elsewhere, though.  However, I also think your code is wrong for what you say you want to do - you say you want a variable, but isn't this defining a function named notSupportedMessage that returns a string and takes the argument "Operating system not supported."?
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
Okay thanks for taking a look at it sirbomber.

I think my code should be calling the constructor on std::string and setting it to "Operating system not supported.". I think this weekend I should be able to put some more time into it.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
You declare static variables inside the class definition, but define static variables outside of the class definition.

Code: [Select]
// XFile.h
class XFile {
private:
  static string notSupportedMessage;
};

// XFile.cpp
string XFile::notSupportedMessage("Operating system not supported.");

Though, considering your message, I wonder if a compile time error might be more appropriate?

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1269
Yeah, this sounds like something you'd want to just use a static_assert for.

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
Thanks Hooman & Arklon,

I wasn't aware of the preprocessor directive #error, which works much better than throwing an error when the code executes in this case.

Thanks for the help!

-Brett

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Edit: Got sidetracked while composing this response. Seems you beat me to #error.

Using static_assert could work. You can also use #error.

Example:
Code: [Select]
#ifdef _WIN32
  // Windows specific code
#elif __linux__
  // Linux specific code
#else
  #error OS not supported
#endif

As per the linked documentation, it doesn't matter if the string after #error is quoted or not.

To use static_assert, instead of #error, it might look something like this:
Code: [Select]
static_assert(false, "OS not supported");

Note: You can't simple use preprocessor #defines such as _WIN32, or __linux__ directly with static_assert, since if they're not defined (normally checked by #ifdef/#ifndef), there is no symbol substitution, so the compiler will see an unknown symbol. Also, to get this to compile under Linux, the newer version of C++ must be explicitly enabled: g++ -std=c++11 cppError.cpp

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1269
The problem with #error is MSVC's syntax for it uses no quotes and GCC's syntax for it does.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Do you have a reference for that? I just went looking to confirm, and couldn't find anything. I did however see a few GCC examples that didn't use quotes.

Admittedly, it looks way better with quotes.

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
Just tested on Visual Studio 2017. MSVC compiles and runs both with or without quotes. However, if you put quotes around the message, the error message will include the quotes. Ideally, the quotes wouldn't be there, but it compiles and gets the message across clearly.

If someone wants to test on GCC we could compare.

Code: [Select]
#if defined (linux)

    . . .

#else
#error "Operating system not supported."
#endif

Results
Code: [Select]
Error (active)	E0035	#error directive: "Operating system not supported." OP2Utility
Code: [Select]
Error	C1189	#error:  "Operating system not supported." OP2Utility

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Tested with GCC:
Code: [Select]
#error OS not supported

Result:
Code: [Select]
cppError.cpp:5:2: error: #error OS not supported
 #error OS not supported
  ^

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
@Hooman,

So this means the GCC compiler supports #error without quotes around the error message?

-Brett

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
It seems to, yes. Though I would see myself using quotes anyway. Just doesn't feel right to me without them.

Similarly I always use parenthesis with sizeof operator, even though they're not required.
Code: [Select]
sizeof(int)
sizeof int

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
Okay, thanks.

I'll review and ensure there are quotes around #error message within XFile.

-Brett