I was writing cross platform code in Visual Studio Community, using C++20 and I am stuck on the output of following code:
#define WINDOWS (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
#define UNIX (defined(__unix__) || defined(__unix))
constexpr bool is_unix1()
{
#ifdef UNIX
return true;
#else
return false;
#endif
}
constexpr bool is_unix2()
{
#ifdef defined(UNIX)
return true;
#else
return false;
#endif
}
int main()
{
cout << std::boolalpha << is_unix1() << " " << is_unix2() << endl;
}
When I ran this code in windows, from inside VS Community itself, I got the following output:
true false
Can someone explain why is_unix1() is evaluated as false while is_unix2() is evaluated as true?
I came to know that defined(...) is compiler specific, and it is not part of standard C++. But directly using the macro is resulting in strange behavior, and I am stuck on which approach to use here.
definedis not compiler-specific. It is specified in the C++ standard.#ifdef defined(UNIX)is simply not valid syntax and a compiler must diagnose this.#ifdefmust be followed by a single identifier and then a new-line. It conditionally compiles code based on whether or not the identifier is defined as a macro.#ifdef UNIXtherefore always compiles the then-branch, because you definedUNIXas a macro beforehand.What you want seems to be something like
#ifconditionally compiles based on a given expression which can includedefinedoperators, which individually evaluate to0or1depending on whether the identifier is defined as a macro.However, you can't hide
(defined(__unix__) || defined(__unix))behind theUNIXmacro and then have it expand in the controlling#ifexpression. If such an expansion results in thedefinedtoken, the behavior of the program is undefined.So what you really want instead of your definition for
UNIXisAnd then later