Search code examples
c++11preprocessor

how can i use preprecessor #if to compare value from compilation with a string


I try to define two differents behaviours in function of the compiler I want to use. I do that because #include <filesystem> doesn't pass with intel compiler.

I use this question to make the following code : How to compare strings in C conditional preprocessor-directives

#include <iostream>

// compares two strings in compile time constant fashion                                                                                                                                                                                                                       
constexpr int c_strcmp( char const* lhs, char const* rhs )
{
  return (('\0' == lhs[0]) && ('\0' == rhs[0])) ? 0
    :  (lhs[0] != rhs[0]) ? (lhs[0] - rhs[0])
    : c_strcmp( lhs+1, rhs+1 );
}

#define COMPILER_INTEL "Intel"
#define COMPILER_GNU "GNU"

#if 0 == c_strcmp(CURRENT_COMPILER, COMPILER_INTEL)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#elif 0 == c_strcmp(CURRENT_COMPILER, COMPILER_GNU)
#include <filesystem>
namespace fs = std::filesystem;
#elif
#error "Compiler unknow"
#endif


int main() {
  std::cout << fs::path("").extension() << std::endl;

  return 0;
}

The line for the compilation is :

icc main.cpp -lstdc++fs -std=c++17 -DCURRENT_COMPILER="Intel" 

I have the following error :

main.cpp(14): error: function call is not allowed in a constant expression
  #if 0 == c_strcmp(CURRENT_COMPILER, COMPILER_INTEL)
           ^

main.cpp(14): error: expression must have integral or enum type
  #if 0 == c_strcmp(CURRENT_COMPILER, COMPILER_INTEL)
                                      ^

main.cpp(17): error: function call is not allowed in a constant expression
  #elif 0 == c_strcmp(CURRENT_COMPILER, COMPILER_GNU)
             ^

main.cpp(17): error: expression must have integral or enum type
  #elif 0 == c_strcmp(CURRENT_COMPILER, COMPILER_GNU)
....

Solution

  • Not exactly an answer to your question but... as far I know, every compiler define a set of specific preprocessor macros to identify the compiler and the exact version of the compiler.

    In this page there is a useful list of this (and other) macros.

    So, I suppose, your code could be simply written as follows

    #ifdef __INTEL_COMPILER
    
    #include <experimental/filesystem>
    namespace fs = std::experimental::filesystem;
    
    #elif defined  __GNU_C__ 
    
    #include <filesystem>
    namespace fs = std::filesystem;
    
    #else
    
    #error "Compiler unknow"
    
    #endif