14

I am writing a program which needs the information of compiler version as the code is compiled.

To simplify the problem, my code is something like

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {

    cout<<"The C++ compiler version is: "<<__STDC_VERSION__<<endl;

    return 0;
}

I would expected once it is compiled and it runs, it would output:

The C++ compiler version is: gcc 5.3.0

I tried to compile it, and got an error:

$ g++ main.cpp 
main.cpp: In function ‘int main(int, char**)’:
main.cpp:24:11: error: ‘__STDC_VERSION__’ was not declared in this scope
     cout<<__STDC_VERSION__<<endl;
           ^

How to correctly get the compiler version in my code?

Einstein_is_Coding
  • 195
  • 1
  • 1
  • 4

4 Answers4

19

I used code like this once:

  std::string true_cxx =
#ifdef __clang__
   "clang++";
#else
   "g++";
#endif

  std::string true_cxx_ver =
#ifdef __clang__
    ver_string(__clang_major__, __clang_minor__, __clang_patchlevel__);
#else
    ver_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#endif

where ver_string was defined:

std::string ver_string(int a, int b, int c) {
  std::ostringstream ss;
  ss << a << '.' << b << '.' << c;
  return ss.str();
}

There's also another useful macro (on gcc and clang) for this:

__VERSION__ This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.

See gcc online docs.

If you need to handle MSVC and other possibilities, you will have to check the macros that they use, I don't remember them off-hand.

Chris Beck
  • 15,614
  • 4
  • 51
  • 87
  • 3
    Note that `__VERSION__` is defined by GCC, not by any standard. – Jonathan Leffler Jul 22 '16 at 16:45
  • 6
    Surely you can do better than having the function returning a string with code such as: `#define STRINGIFY(x) #x` and `#define VER_STRING(major, minor, patch) STRINGIFY(major) "." STRINGIFY(minor) "." STRINGIFY(patch)`. Then you could use `std::string true_cxx_ver = VER_STRING(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);`. – Jonathan Leffler Jul 22 '16 at 17:01
  • Yeah I agree, that is much better. I forgot that you can stringify numbers likes that. – Chris Beck Jul 23 '16 at 03:44
7

If for some reason we are using the Boost library in our project, we can use macros that are defined in #include <boost/config.hpp>.

The following code:

std::string get_compile_version()
{
     char buffer[sizeof(BOOST_PLATFORM) + sizeof(BOOST_COMPILER) +sizeof(__DATE__ )+ 5];
     sprintf(buffer, "[%s/%s](%s)", BOOST_PLATFORM, BOOST_COMPILER, __DATE__);
     std::string compileinfo(buffer);
     return compileinfo;
}

to std::cout prints the following on my machine:

[Win32/Microsoft Visual C++ version 14.1](May 10 2019)

Other related macros are listed here.

alfC
  • 14,261
  • 4
  • 67
  • 118
Malick
  • 6,252
  • 2
  • 46
  • 59
  • That's good.. Is there a way to print also the architecture (x86 vs x64)? – Jepessen Nov 09 '19 at 15:25
  • 1
    I don't think via boost, as a workaround you can use a #ifdef directive (https://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c) and a harcoded string for the architecture. – Malick Nov 09 '19 at 17:19
  • 3
    Since these macros are string literals you can just do `const char* get_compile_version() { return "[" BOOST_PLATFORM "/" BOOST_COMPILER "](" __DATE__ ")"; }` – Artyer Oct 18 '20 at 17:18
3

__STDC_VERSION__ is the version of the C standard library. It's not part of C++, and it's not the compiler's version.

From GCC's documentation:

This macro is not defined if the -traditional-cpp option is used, nor when compiling C++ or Objective-C.

It's equivalent is __cplusplus, which will tell you the C++ standard version used by the compiler.

Compiler version macros are vendor specific, for GCC they are __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__

Dutow
  • 5,638
  • 1
  • 30
  • 40
2

For MSVC following code:

#ifdef _MSC_VER
    std::to_string(_MSC_VER)
#endif

could be used.

Aleksey Kontsevich
  • 4,671
  • 4
  • 46
  • 101