Ghasem Ramezani
Ghasem Ramezani

Reputation: 2888

Is it possible to compile a project with two different language standards?

I have a project which is strictly written in C++14 and I want to use it in another project which is C++17. Some of the C++14 features like Dynamic Exception Specification were removed in C++17.

Is there any way to use and compile both code bases together? The project is large enough to make refactoring impractical.

Upvotes: 4

Views: 997

Answers (2)

Jan Schultke
Jan Schultke

Reputation: 39774

Yes, you can detect the C++ version and compile conditionally:

void foo() {
#if __cplusplus >= 201703L
    // code written for C++17 goes here
#else
    // code written for C++14 goes here
#endif
}

The full list of __cplusplus macros is as follows:

#if __cplusplus >= 199711L // C++98
#if __cplusplus >= 201103L // C++11
#if __cplusplus >= 201402L // C++14
#if __cplusplus >= 201703L // C++17
#if __cplusplus >= 202002L // C++20

Note that this causes various problems:

  • it's impossible to test code like this unless you compile your tests for C++14 and C++17 separately
  • your IDE might not even show warnings or errors in removed preprocessed blocks
  • you need to maintain two separate version of the same code

So if you can, come up with a solution that works in both versions or at least use as few blocks like this as possible. If you just want a single keyword or so to be removed, then consider the following solution:

#if __cplusplus >= 201703L // C++17
#define THROWS(...) noexcept(false)
#else
#define THROWS(...) throw(__VA_ARGS__)
#endif

// now you can use it like this in both C++14 and C++17:
void fun() THROWS(MyException);

Upvotes: 2

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16039

This will be platform specific: It is conceivable that substantially different headers are selected according to the standard specified on the command line, etc.

That said, here is an answer from Jonathan Wakely which assures you that with gcc there should be no such problem, by design, if you keep away from unstable features in old compilers.

The underlying reason according to Jonathan is that C++ standard implementations in gcc, once declared stable, do not change their ABI (i.e, outward-facing type definitions, name mangling) with the selected C++ standard, not even between compiler versions.

Because all interaction between the translation units must be restricted to the smallest common standard version there is no issue: The C++11 features do not change if you specify C++17. Newer features in the C++17 TUs cannot be used for communication with earlier-standard TUs since they were not yet available, so no issue there either. If you are able to recompile, the safest advice would be:

  1. Best to use the same std::string versions (which can be controlled from the command line at compile time).
  2. Use the same libstdc++.
  3. Use the same gcc version (and control the language standard used for each TU through the command line).

It would make sense for other compilers to follow a similar compatibility strategy.

Upvotes: 2

Related Questions