I did read this question: How to detect C++11 support in CMake. It basically tells me that CMake's support for detecting C++ features is very sophisticated when you want to fail generation if a certain compiler does NOT support the feature you are using in your code but also extremely limited when you want to react on this at generation time without failing.
What I would like to be able to do is not to fail but e.g. to define a different set of source files if certain features are not available in order to allow compilation of old c++03 code if needed and use the newer c++11-... ones if possible. Something like this would be great:
set(TARGET MyTarget)
if(CPP_STANDARD_VERSION GREATER_EQUAL 11)
set(SOURCE myModernFile.cpp)
else()
set(SOURCE myLegacyFile.cpp)
endif()
add_executable(${TARGET} ${SOURCE })
if(CPP_STANDARD_VERSION GREATER_EQUAL 11)
# Here failing would be fine if lambdas are not supported!
target_compile_features(${TARGET} PRIVATE cxx_lambdas)
endif()
When following this approach as recommended in the linked question:
foreach(i ${CMAKE_CXX_COMPILE_FEATURES})
message("${i}")
endforeach()
e.g. with Visual Studio 2013 with CMake 3.13.2 I am getting the following output:
cxx_std_98
cxx_std_11
cxx_std_14
cxx_std_17
cxx_std_20
cxx_alias_templates
cxx_auto_type
cxx_contextual_conversions
cxx_decltype
cxx_default_function_template_args
cxx_defaulted_functions
cxx_delegating_constructors
cxx_enum_forward_declarations
cxx_explicit_conversions
cxx_extended_friend_declarations
cxx_extern_templates
cxx_final
cxx_generalized_initializers
cxx_lambdas
cxx_local_type_template_args
cxx_long_long_type
cxx_nullptr
cxx_override
cxx_range_for
cxx_raw_string_literals
cxx_right_angle_brackets
cxx_rvalue_references
cxx_static_assert
cxx_strong_enums
cxx_template_template_parameters
cxx_trailing_return_types
cxx_uniform_initialization
cxx_variadic_macros
cxx_variadic_templates
To me the list makes sense for the specific features, but the general ones with the supported C++ standards apparently cannot be right as VS 2013 does not support C++20. Am I missing something?
Right now I ended up with more or less the same approach as described in the linked question: I check various compiler versions manually and then depending on that I set my CPP_STANDARD_VERSION property, but this seems very fragile to me. Is there really no other way?