From 52b8f6095363d2646eaeab9ad84915ed9002fcc4 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 22 Dec 2017 08:49:21 +0100 Subject: [PATCH] Add std::index_sequence for C++11 Will be required for nasal::Ghost --- CMakeLists.txt | 26 +++++--- simgear/misc/CMakeLists.txt | 4 ++ simgear/misc/integer_sequence.hxx | 86 ++++++++++++++++++++++++++ simgear/misc/integer_sequence_test.cxx | 47 ++++++++++++++ simgear/simgear_config_cmake.h.in | 2 +- 5 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 simgear/misc/integer_sequence.hxx create mode 100644 simgear/misc/integer_sequence_test.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index bbf4e46c..9f1a0b2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,16 @@ include (DetectArch) # keep the compatability link option as the default option(OSG_FSTREAM_EXPORT_FIXED "Set to ON if the osgDB fstream export patch is applied" OFF) +if (CMAKE_COMPILER_IS_GNUCXX OR CLANG) + if (CMAKE_VERSION VERSION_LESS 3.1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++${CMAKE_CXX_STANDARD}") + elseif (CMAKE_VERSION VERSION_LESS 3.8) + # policy CMP0067 (try_compile does not honor CMAKE_CXX_STANDARD) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++${CMAKE_CXX_STANDARD}") + endif() +endif() + + if (MSVC) GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH) if (CMAKE_CL_64) @@ -382,10 +392,6 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(WARNING_FLAGS_CXX "-Wall -fPIC") set(WARNING_FLAGS_C "-Wall -fPIC") - if (CMAKE_VERSION VERSION_LESS 3.1) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) message(WARNING "GCC 4.4 will be required soon, please upgrade") endif() @@ -413,10 +419,6 @@ if (CLANG) # fix Boost compilation :( set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - if (CMAKE_VERSION VERSION_LESS 3.1) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - if(ENABLE_SIMD) if (X86 OR X86_64) set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse") @@ -489,6 +491,14 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS_C} ${MSVC_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}") +check_cxx_source_compiles(" + #include + #include + std::make_index_sequence<0> t; + int main() { return 0; }" + HAVE_STD_INDEX_SEQUENCE +) + # use BEFORE to ensure local directories are used first, # ahead of system-installed libs include_directories(BEFORE ${PROJECT_BINARY_DIR}/simgear) diff --git a/simgear/misc/CMakeLists.txt b/simgear/misc/CMakeLists.txt index 2931a3b3..3c5bfedd 100644 --- a/simgear/misc/CMakeLists.txt +++ b/simgear/misc/CMakeLists.txt @@ -56,6 +56,10 @@ add_executable(test_CSSBorder CSSBorder_test.cxx) add_test(CSSBorder ${EXECUTABLE_OUTPUT_PATH}/test_CSSBorder) target_link_libraries(test_CSSBorder ${TEST_LIBS}) +add_executable(test_integer_sequence integer_sequence_test.cxx) +add_test(integer_sequence ${EXECUTABLE_OUTPUT_PATH}/test_integer_sequence) +target_link_libraries(test_integer_sequence ${TEST_LIBS}) + add_executable(test_tabbed_values tabbed_values_test.cxx) add_test(tabbed_values ${EXECUTABLE_OUTPUT_PATH}/test_tabbed_values) target_link_libraries(test_tabbed_values ${TEST_LIBS}) diff --git a/simgear/misc/integer_sequence.hxx b/simgear/misc/integer_sequence.hxx new file mode 100644 index 00000000..300fc9ea --- /dev/null +++ b/simgear/misc/integer_sequence.hxx @@ -0,0 +1,86 @@ +///@file +/// Metaprogramming Integer sequence (Is in C++14 but not C++11) +// +// Copyright (C) 2017 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ +#define SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ + +#include +#include + +#ifndef HAVE_STD_INDEX_SEQUENCE +# include + +namespace std +{ + template + struct integer_sequence + { + static_assert( + std::is_integral::value, + "std::integer_sequence can only be instantiated with an an integral type" + ); + + typedef T value_type; + static constexpr size_t size() noexcept { return sizeof...(Ints); } + }; +} + +namespace simgear { namespace detail +{ + template + struct append; + + template + struct append, Int> + { + using type = std::integer_sequence; + }; + + template + struct sequence_gen + { + using type = + typename append::type, N - 1>::type; + }; + + template + struct sequence_gen + { + using type = std::integer_sequence; + }; +}} + +namespace std +{ + template + using index_sequence = integer_sequence; + + template + using make_integer_sequence = + typename simgear::detail::sequence_gen::type; + + template + using make_index_sequence = make_integer_sequence; + + template + using index_sequence_for = make_index_sequence; +} +#endif + +#endif /* SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ */ diff --git a/simgear/misc/integer_sequence_test.cxx b/simgear/misc/integer_sequence_test.cxx new file mode 100644 index 00000000..82463f50 --- /dev/null +++ b/simgear/misc/integer_sequence_test.cxx @@ -0,0 +1,47 @@ +#include "integer_sequence.hxx" + +#include + +template +void print(const T& v, std::size_t i) +{ + std::cout << "arg #" << i << ": '" << v << "', "; +} + +template +void doIt_impl(Args ... args, std::index_sequence) +{ + std::initializer_list{(print(args, Is), '0')...}; +} + +template +void doIt(Args ... args) +{ + static_assert(sizeof...(Args) == std::index_sequence_for::size(), ""); + + doIt_impl(args..., std::index_sequence_for{}); +} + +int main(int argc, char* argv[]) +{ + static_assert(std::is_same::value_type, char>::value, ""); + static_assert(std::is_same::value_type, long long>::value, ""); + static_assert(std::is_same::value_type, std::size_t>::value, ""); + + static_assert(std::is_same, std::index_sequence<>>::value, ""); + static_assert(std::is_same, std::index_sequence<0>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2, 3>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2, 3, 4>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2, 3, 4, 5>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2, 3, 4, 5, 6>>::value, ""); + static_assert(std::is_same, std::index_sequence<0, 1, 2, 3, 4, 5, 6, 7>>::value, ""); + + static_assert(std::make_index_sequence<5>::size() == 5, ""); + static_assert(std::index_sequence_for::size() == 3, ""); + + std::cout << std::make_integer_sequence::size() << std::endl; + doIt(1, 2, 3, "hallo", 3.4, 3.52f); + return 0; +} diff --git a/simgear/simgear_config_cmake.h.in b/simgear/simgear_config_cmake.h.in index 0282aca1..b68991da 100644 --- a/simgear/simgear_config_cmake.h.in +++ b/simgear/simgear_config_cmake.h.in @@ -15,7 +15,7 @@ #cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_MKDTEMP #cmakedefine HAVE_AL_EXT_H - +#cmakedefine HAVE_STD_INDEX_SEQUENCE #cmakedefine GCC_ATOMIC_BUILTINS_FOUND