2

I'm building a C++ library with CMake. Is it possible to set the C++ standard to the newest released standard supported by the user's compiler? I checked the docs for the variable CXX_STANDARD, but it only shows how to use one specific standard.

Motivation:

I want my library to be compatible with C++11, but I also want to use the features of newer C++ standards if they're available. For example, I have defined the following macro.

#if (__cplusplus > 201700L || _MSVC_LANG > 201700L)
#define IF_CONSTEXPR_MACRO if constexpr
#else
#define IF_CONSTEXPR_MACRO if
#endif

This is great for header-only libraries because

  1. The code is compatible with old C++ standards, and
  2. If the user compiles with C++17 or newer, they get all the advantages of constexpr if.

Unfortunately, my library is not header only. I want the resulting .so file to use the if constexpr version if it is available.

starball
  • 20,030
  • 7
  • 43
  • 238
  • If you're trying to compile the .so _once_ and have it support multiple language standards, you can pretty much forget it unless you duplicate your functions, data structures _etc_ with a whole log of magic macro flavoring. If the library user will actually compile it themselves with their required language standard, then this is not so much of an issue, but you'll still need macro magic to conditionally enable select language features. – paddy Jul 26 '23 at 22:57
  • Are you saying that if the user compiles my library into a .so with std=c++20, for example, then they won't be able to link it with their own code if it uses std=c++17 or older? – Shawn McAdam Jul 26 '23 at 23:14
  • @paddy Macro magic is not a concern to me, because my question includes all the macro magic required to conditionally enable at least one useful language feature – Shawn McAdam Jul 26 '23 at 23:15
  • If the interface automatically compiles with c++20 features, and you try to link it in a project that uses c++17 features, then you're out of luck. BUT, if your library only uses the c++20 features _internally_ (as in, those do not affect any of the interface), it's fine. – paddy Jul 26 '23 at 23:17
  • @paddy yeah, the newer C++ features do not affect the interface in my case. I'm really just using the constexpr if example internally wherever an if statement can be decided at compile time (but doesn't necessarily have to be). – Shawn McAdam Jul 26 '23 at 23:23
  • If that stuff is not required as part of the actual library interface, don't expose it at all. If it _is_ required (for example, if your library exposes any templates that use it), then at the very least you should prefix the macros with your library name. – paddy Jul 26 '23 at 23:33
  • Technically you may be able to use [`try_compile`'s project version](https://cmake.org/cmake/help/latest/command/try_compile.html#try-compiling-whole-projects) and increment the C++ standard used in increment by 3 until the project no longer works. However this seems like a bad idea to me: Either `if constexpr` is required to make the code compile at which point your code doesn't work with C++ versions that are too old or you've got an effect that should most likely give you the same effect with the C++17 standard available as a decent optimizer with prior standards... – fabian Jul 27 '23 at 18:45

1 Answers1

1

For MSVC, you can wrap a compiler ID generator expression around /std:c++latest. For the other compilers you might need to do multiple checks with CheckCXXCompilerFlag. Honestly, if the compiler version used to compile your target really doesn't matter, it would be a lot simpler to just tell your user to use whatever they want / have.

I'm getting some XY problem vibes from the scenario you've described. If the code using that macro is equally valid with if or if constexpr, then you don't really need if constexpr there, and can probably just trust your compiler to do optimizations (which I assume is what you're trying to achieve with that macro).

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
starball
  • 20,030
  • 7
  • 43
  • 238
  • Thanks, CheckCXXCompilerFlag looks very promising! Yes, most of my use cases are probably optimized away. Another example that can be implemented similarly to my IF_CONSTEXPR_MACRO is the C++20 keywords [[likely]] or [[unlikely]]. I'm thinking that they're worth using if they're available, but nobody should make C++20 the minimum standard of their library just to use those keywords. – Shawn McAdam Jul 27 '23 at 01:23