├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── _test ├── CMakeLists.txt └── main.cpp ├── comp_base.cmake ├── cpp11_lang.cmake ├── cpp11_lang ├── alias_template.cmake ├── alignas.cmake ├── alignof.cmake ├── auto_type.cmake ├── constexpr.cmake ├── decltype.cmake ├── default_function_template_args.cmake ├── delete_fnc.cmake ├── enum_class.cmake ├── explicit_conversion_op.cmake ├── final.cmake ├── inline_namespace.cmake ├── lambdas.cmake ├── literal_op.cmake ├── noexcept.cmake ├── noreturn.cmake ├── nullptr.cmake ├── override.cmake ├── parameter_pack.cmake ├── range_for.cmake ├── right_angle_brackets.cmake ├── rvalue_ref.cmake ├── static_assert.cmake └── thread_local.cmake ├── cpp11_lib.cmake ├── cpp11_lib ├── get_new_handler.cmake ├── get_terminate.cmake ├── is_trivially.cmake ├── max_align_t.cmake ├── mutex.cmake └── to_string.cmake ├── cpp14_lang.cmake ├── cpp14_lang ├── deprecated.cmake ├── general_constexpr.cmake ├── return_type_deduction.cmake ├── sized_deallocation.cmake └── variable_template.cmake ├── cpp14_lib.cmake ├── cpp14_lib ├── exchange.cmake ├── generic_operator_functors.cmake ├── integer_sequence.cmake ├── make_unique.cmake ├── quoted.cmake ├── shared_lock.cmake └── two_range_algorithms.cmake ├── cpp17_lang.cmake ├── cpp17_lang ├── fold_expressions.cmake ├── terse_static_assert.cmake └── utf8_char_literal.cmake ├── cpp17_lib.cmake ├── cpp17_lib ├── bool_constant.cmake ├── container_access.cmake ├── invoke.cmake ├── map_insertion.cmake ├── shared_mutex.cmake ├── uncaught_exceptions.cmake └── void_t.cmake ├── env.cmake ├── env ├── exception_support.cmake ├── hosted_implementation.cmake ├── rtti_support.cmake └── threading_support.cmake ├── ext.cmake ├── ext ├── assume.cmake ├── bswap.cmake ├── clz.cmake ├── counter.cmake ├── ctz.cmake ├── expect.cmake ├── extension.cmake ├── fallthrough.cmake ├── has_include.cmake ├── int128.cmake ├── popcount.cmake ├── pretty_function.cmake ├── unreachable.cmake └── unused.cmake ├── ts.cmake └── ts ├── any.cmake ├── apply.cmake ├── container_erasure.cmake ├── logical_operator_traits.cmake ├── make_array.cmake ├── not_fn.cmake ├── optional.cmake ├── pmr.cmake └── string_view.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | 3 | CMakeCache.txt 4 | CMakeFiles/ 5 | 6 | #vscode 7 | .vscode/ 8 | 9 | # Jetbrains 10 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | addons: 4 | apt: 5 | sources: 6 | - ubuntu-toolchain-r-test 7 | packages: 8 | - g++-5 9 | 10 | install: 11 | - wget --no-check-certificate https://www.cmake.org/files/v3.3/cmake-3.3.1-Linux-x86_64.tar.gz 12 | - tar -xzf cmake-3.3.1-Linux-x86_64.tar.gz 13 | - export CC='gcc-5' 14 | - export CXX='g++-5' 15 | script: 16 | - mkdir build && cd build/ 17 | - ../cmake-3.3.1-Linux-x86_64/bin/cmake ../_test 18 | - ../cmake-3.3.1-Linux-x86_64/bin/cmake --build . 19 | - ./comp_test 20 | - rm -r * 21 | - ../cmake-3.3.1-Linux-x86_64/bin/cmake -D_COMP_TEST_WORKAROUND=ON ../_test 22 | - ../cmake-3.3.1-Linux-x86_64/bin/cmake --build . 23 | - ./comp_test 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015-2016 Jonathan Müller 2 | 3 | This software is provided 'as-is', without any express or 4 | implied warranty. In no event will the authors be held 5 | liable for any damages arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute 9 | it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; 12 | you must not claim that you wrote the original software. 13 | If you use this software in a product, an acknowledgment 14 | in the product documentation would be appreciated but 15 | is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, 18 | and must not be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any 21 | source distribution. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compatibility 2 | 3 | [![Build Status](https://travis-ci.org/foonathan/compatibility.svg?branch=master)](https://travis-ci.org/foonathan/compatibility) 4 | 5 | This library provides an advanced `target_compile_features()` and `write_compiler_detection_header()`. 6 | The problem with those is that they are controlled via a CMake internal database, which has to be kept manually up-to-date. 7 | This version uses `check_cxx_source_compiles()` instead and is such automatically up-to-date - a compiler supports a feature, 8 | if the test code compiles. 9 | 10 | Based on the test results, a header file is generated that stores the result and often workaround code, 11 | for example a `CONSTEXPR` macro that is `constexpr`, if supported, and `const` otherwise, 12 | to use the features anyway. 13 | 14 | It also provides the automatic standard deduction from `target_compile_features()` to activate the right standard. 15 | 16 | ## Example 17 | 18 | If you only want the C++ standard activation, simply `include()` `comp_base.cmake` and replace `target_compile_features()` by `comp_compile_features()`. 19 | 20 | This is a `CMakeLists.txt` for a more advanced usage: 21 | ``` 22 | # suppose we have a target 'tgt' 23 | include(your/dir/to/comp_base.cmake) # only file you need to download, rest is taken as needed 24 | 25 | # we want constexpr, noexcept, std::max_align_t and rtti_support 26 | # instead of cpp11_lang/constexpr and cpp11_lang/noexcept, you could also write cxx_constexpr/cxx_noexcept 27 | comp_target_features(tgt PUBLIC cpp11_lang/constexpr cpp11_lang/noexcept cpp11_lib/max_align_t env/rtti_support) 28 | ``` 29 | 30 | For convenience we include all generated files in a header named `config.hpp`. 31 | The filenames are made available through macros. 32 | 33 | ```cpp 34 | #ifndef CONFIG_HPP 35 | #define CONFIG_HPP 36 | 37 | #include COMP_CONSTEXPR_HEADER 38 | #include COMP_NOEXCEPT_HEADER 39 | #include COMP_MAX_ALIGN_T_HEADER 40 | #include COMP_RTTI_SUPPORT_HEADER 41 | 42 | #endif 43 | ``` 44 | 45 | And then we can use it just by including `config.hpp` in our code: 46 | 47 | ```cpp 48 | #include "config.hpp" 49 | 50 | // use a workaround macro 51 | COMP_CONSTEXPR int i = 0; 52 | 53 | void func() COMP_NOEXCEPT 54 | { 55 | // use a workaround typedef 56 | comp::max_align_t foo; 57 | 58 | // or conditional compilation 59 | #if COMP_HAS_RTTI_SUPPORT 60 | do_sth(); 61 | #endif 62 | } 63 | ``` 64 | 65 | If you don't care about the workarounds, but just want a specific standard, simply call: 66 | ``` 67 | comp_target_features(tgt PUBLIC CPP11) # or CPP14 or CPP17 68 | ``` 69 | This will only activate C++11/14/17 without doing anything else. 70 | 71 | *Note: The standard activation is always `PRIVATE` to allow users of a library to have a different (higher) standard than the library.* 72 | 73 | ## Usage 74 | 75 | The only file needed is `comp_base.cmake`. 76 | You can either manually download it, use CMakes `file(DOWNLOAD` facility, 77 | or use git submodules. 78 | The branch `git-submodule` only contains `comp_base.cmake` and is thus perfect for this purpose. 79 | Run `git submodule add -b "git-submodule" https://github.com/foonathan/compatibility.git` to initialize it and fetch the file. 80 | Then you only need to run `git submodule update --remote` to update it to the newest version. 81 | 82 | `include()` it in your `CMakeLists.txt` now. 83 | First it generates CMake options - `COMP_CPP11_FLAG`, `COMP_CPP14_FLAG` and `COMP_CPP17_FLAG` - storing the calculated compiler flag for a given standard, 84 | useful if you want to override it, if it can't find one for your compiler. 85 | It also provides the following function: 86 | 87 | comp_target_features( 88 | [NOPREFIX | PREFIX ] 89 | [CMAKE_PATH ] [INCLUDE_PATH ] 90 | [NOFLAGS | CPP11 | CPP14 | CPP17] 91 | [LOG ] 92 | [NO_HEADER_MACROS] [SINGLE_HEADER ]) 93 | 94 | Ignoring all the other options, it is like `target_compile_features()`. 95 | It takes a list of features to activate for a certain target. 96 | A features is a file in this repository without the `.cmake` extension, e.g. `cpp11_lang` for all C++11 language features, 97 | or `cpp14_lang/deprecated` for the C++14 deprecated features. 98 | 99 | A feature file with name `dir/xxx.cmake` belonging to a feature `dir/xxx` consists of the following, 100 | where `dir` is the category of the feature, `xxx` the feature name in lowercase, `XXX` the feature name in upper case `` the prefix as given to the function, `` the prefix in lowercase and without a trailing underscore: 101 | 102 | * a test testing whether or not the compiler supports this feature 103 | 104 | * a CMake option with name `COMP_HAS_XXX` to override its result, useful if you want to act like it doesn't support a feature, 105 | or if the test is poorly written (please contact me in this case!) 106 | 107 | * a header named `/xxx.hpp`. 108 | The header contains at least a macro `HAS_XXX` with the same value as the CMake option 109 | and often workaround macros or functions that can be used instead of the feature. 110 | The workaround uses either the feature, if it is available, or own code. 111 | This allows using many new features already, without support. 112 | If the compiler gets support, you will be automatically using the native feature or the standard library implementation. 113 | 114 | * a globally available macro named `_XXX_HEADER` to include the header file. 115 | 116 | To use the generated header files, simply write `#include _XXX_HEADER` inside your code, the macro is made available automatically (you could also `#incluce` the file directly but this is not recommended). 117 | 118 | What `comp_target_features` function actually does is the following: 119 | 120 | * For each feature, it downloads the latest version of the test file from Github, if it doesn't exist yet. 121 | The remote url can be set via the option `COMP_REMOTE_URL`. 122 | 123 | * For each feature, it calls `include(feature.cmake)` after some set up. This runs the test and generates the header file. 124 | 125 | * It calls `target_include_directories` to allow including the generated header files 126 | and `target_compile_definitions` for the file macro. 127 | The `INTERFACE/PUBLIC/PRIVATE` specifier are only used in these calls. 128 | 129 | * Activates the right C++ standard. E.g., if a feature requires C++11, it will be activated if it is available. If it is not, it will only activate the C++ standard required by the workaround code. This activation is always `PRIVATE`. The flag is exposed through the CACHE variable `${target}_COMP_COMPILE_OPTIONS`. 130 | 131 | The behavior can be customized with the other options: 132 | 133 | * `NOPREFIX`/`PREFIX`: The prefix of any generated macros or none if `NOPREFIX` is set. Default is `COMP_`. 134 | 135 | * `NAMESPACE`: The namespace name of any generated code, default is `comp`. A given prefix must always use the same namespace name! 136 | 137 | * `CMAKE_PATH`/`INCLUDE_PATH`: The download destination for the CMake files/the destination of the generated headers, 138 | default is `${CMAKE_BINARY_DIR}/comp.downloaded` for cmake and `${CMAKE_BINARY_DIR}/comp.generated` for the headers. 139 | `INCLUDE_PATH` is also given to `target_include_directories()`, but note that the generated headers are in a subfolder `` (this cannot be changed). 140 | 141 | * `NOFLAGS`/`CPP11`/`CPP14`/`CPP17`: Override for the standard detection, if you want to have a newer standard than deduced from the features, 142 | or a lower (not recommended). They have priority over the deduction, C++17 over C++14 over C++11. 143 | Specify `NOFLAGS` if you do not want to have any compiler flags set. 144 | The latter is useful for `INTERFACE` libraries which are only there to run the tests and generate the options and headers. 145 | 146 | * `LOG`: Turn down or up the logging for features. There is no default value, but it is fairly verbose by default. 147 | * Possible options: `DEBUG`, `INFO`, `QUIET`, `SILENT`, `ALL` 148 | * Additionally, setting `COMP_LOG_LEVEL` at the global level behaves the same way, except any option passed here will *override* for the current run 149 | 150 | * `NO_HEADER_MACROS`: Disables the definition of the macros that contain the header file location. 151 | 152 | * `SINGLE_HEADER`: Generate a single header file with that name that will include all generated headers. 153 | 154 | ## Feature Reference 155 | 156 | A feature named `dir/xxx` is tested in `xxx.cmake`, defines an override CMake option `COMP_HAS_XXX` and a macro `HAS_XXX` in a file named `/xxx.hpp` (where `prefix` is `` in lowercase without a trailing underscore), filename also made available over the global macro `XXX_HEADER`. 157 | 158 | There are also alternative names for the CMake `target_compile_features()` and SD-6 Feature Test Recommondations that are automatically translated. 159 | Where appropriate, it will also generate the SD-6 feature macro as specified. 160 | This will override the existing value if the new one is greater or the macro `COMP_OVERRIDE_SD6` is defined. 161 | If a feature is not supported, it will not change or define anything. 162 | 163 | For some features, macros are generated that can be used instead (i.e. for `noexcept`), they have the form `XXX`. 164 | Those macros often use compiler extensions. 165 | If there is none (or a lacking implementation...), an error message will be emmitted. 166 | To prevent this, simply define the macro as no-op or as you want prior to including the file. 167 | 168 | There are often workaround functions for library features. Those are defined in a namespace and either use the own implementation or the standard library implementation, if it is available. 169 | 170 | Prefix and namespace name can be controlled via parameters, see above. 171 | A given prefix must always use the same namespace name on each call. 172 | 173 | This library currently tests for the following features. 174 | The code below assumes no prefix and a namespace name of `comp`. 175 | 176 | *A feature will only be included (by me) if it is not a pure syntactic feature (like `auto` or lambdas which can be avoided) but if there is either sensible workaround code, e.g. through to compiler extensions or through reimplementing (small!) standard library functionality, or there can be conditional compilation based on the existense, e.g. optional literal definitions or move constructors. 177 | 178 | Note that I'm open to PRs of any kind :)* 179 | 180 | ### C++11 language features 181 | 182 | These features are all in the subdirectory `cpp11_lang`. 183 | 184 | feature name|alternative name|example|workaround, if any 185 | ------------|----------------|-------|------------------ 186 | alias_template|cxx_alias_templas|`template using my_map = std::map;`|no workaround 187 | alignas|cxx_alignas|`alignas(int) char c`|`ALIGNAS(x)`, fallback to compiler extension, if available 188 | alignof|cxx_alignof|`alignof(int)`|`ALIGNOF(x)`, fallback to compiler extension, if available 189 | auto_type|cxx_auto_type|`auto var = 0`|no workaround 190 | constexpr|cxx_constexpr|`constexpr int foo()`|`CONSTEXPR`, fallback to `const`; `CONSTEXPR_FNC`, fallback to `inline` 191 | decltype|cxx_decltype|`decltype(a)`|`DECLTYPE(x)`, fallback to `typeof` extension, if available 192 | default_function_template_args|cxx_default_function_template_args|`template void foo();`| no workaround 193 | delete_fnc|cxx_deleted_functions|`void foo() = delete;`|no workaround 194 | enum_class|cxx_strong_enum|`enum class foo {}`|no workaround 195 | explicit_conversion_op|cxx_explicit_conversion|`explicit operator bool()`|no workaround 196 | final|cxx_final|`void bar() final;`|`FINAL` macro, workaround expands to nothing 197 | inline_namespace|none|`inline namespace foo {...}`|no workaround 198 | lambdas|cxx_lambdas|`[](){}`|no workaround 199 | literal_op|cxx_user_literals|`operator""`|no workaround 200 | noexcept|cxx_noexcept|`void foo() noexcept;`|`NOEXCEPT`, fallback to nothing; `NOEXCEPT_IF(x)`, fallback to nothing; `NOEXCEPT_OP(x)`, fallback to `false` 201 | noreturn|none|`[[noreturn]] void foo();`|`NORETURN`, fallback to compiler extension, if available 202 | nullptr|cxx_nullptr|`void* ptr = nullptr;`|`NULLPTR`, fallback to [null pointer idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr); also `comp::nullptr_t` 203 | override|cxx_override|`void bar() override;`|`OVERRIDE`, fallback to nothing 204 | parameter_pack|cxx_parameter_pack|`template void f(T... ts);`|no workaround 205 | range_for|cxx_range_for|`for (auto var : container)`|no workaround 206 | right_angle_brackets|cxx_right_angle_brackets|`std::vector>`|no workaround 207 | rvalue_ref|cxx_rvalue_references|`int&& a = 4;`|no workaround 208 | static_assert|cxx_static_assert|`static_assert(std::is_integral::value, "");`|`STATIC_ASSERT(Expr, Msg)`, fallback to simple undefined struct technique 209 | thread_local|cxx_thread_local|`thread_local int i;`|`THREAD_LOCAL`, fallback to `__thread` extension or similar, if available - **does not call constructors or destructors!** 210 | 211 | *Note: In general, it assumes proper C++11 support. The workarounds defined in this library rely on all common C++ features that can not be easily avoided except those listed here with a proper fallback (like `noexcept`, `constexpr`, ...).* 212 | 213 | Get them all by specifying `cpp11_lang`. 214 | 215 | ### C++11 library features 216 | 217 | These features are all in the subdirectory `cpp11_lib`. 218 | 219 | feature name|example|workaround, if any 220 | ------------|-------|------------------ 221 | get_new_handler|`std::get_new_handler()`|`comp::get_new_handler()`, fallback to old `std::set_new_handler(nullptr)` technique - **not thread safe** 222 | get_terminate|`std::get_terminate()`|`comp::get_terminate()`, same as above 223 | is_trivially|`std::is_trivially_XXX`|`comp::is_trivially_XXX`, workaround uses `std::is_XXX` combined with `std::is_trivial` 224 | max_align_t|`std::max_align_t`|`comp::max_align_t`, fallback to `::max_align_t` or a struct with a `long double` and `long long` 225 | mutex|`std::mutex`/`std::lock_guard`/`std::unique_lock`|no workaround 226 | to_string|`std::to_string(54)`|`comp::to_string()`, fallback to `std::sprintf()` 227 | 228 | *Note: It only checks for minor features where an easy workaround implementation is feasible in the scope of this library.* 229 | 230 | Get them all by specifying `cpp11_lib`. 231 | 232 | ### C++14 language features \[complete\] 233 | 234 | These features are all in the subdirectory `cpp14_lang`. 235 | 236 | paper|feature name|alternative name|example|workaround, if any 237 | -----|------------|----------------|-------|------------------ 238 | [N3760](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3760.html)|deprecated|cxx_attribute_deprecated|`[[deprecated]] int foo();`|`DEPRECATED` and `DEPRECATED(Msg)`, fallback to compiler attribute, if available 239 | [N3652](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3652.html)|general_constexpr|cxx_relaxed_constexpr|generalized constexpr|no workaround 240 | [N3638](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3638.html)|return_type_deduction|none|auto return type deduction for normal functions|`AUTO_RETURN` macro 241 | [N3778](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3778.html)|sized_deallocation|none|`void operator delete(void *ptr, std::size_t size)`|no workaround 242 | [N3651](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3651.html)|variable_template|cxx_variable_templates|`template T pi;`|no workaround 243 | 244 | Get them all by specifying `cpp14_lang`. 245 | 246 | The following features are not and will never be supported: 247 | 248 | paper|description|reason 249 | -----|-----------|------ 250 | [N3323](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3323.pdf)|Tweak Certain C++ Contextual Conversions|difficult to check, avoid relying on behavior 251 | [N3472](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3472.pdf)|Binary Literals|syntax sugar only 252 | [N3648](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3648.html)|Generalized Lambda Capture|lambdas are syntax sugar only 253 | [N3649](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3649.html)|Generic Lambdas|lambdas are syntax sugar only 254 | [N3653](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3653.html)|Member initializers and aggregates|difficult to check, no big user impact 255 | [N3664](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3664.html)|Clarifying Memory Allocation|wording change only 256 | [N3781](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3781.pdf)|Digit seperator for literals|syntax sugar only 257 | 258 | ### C++14 library features \[complete\] 259 | 260 | These features are all in the subdirectory `cpp14_lib`. 261 | 262 | paper|feature name|example|workaround, if any 263 | --------|------------|-------|------------------ 264 | [N3668](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3668.htm)|exchange|`std::exchange()`|`comp::exchange()`, own implementation 265 | [N3421](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3421.html)|generic_operator_functors|`std::greater<>{}`|`comp::greater{}` and the rest, no class templates! 266 | [N3658](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3658.html)|integer_sequence|`std::index_sequence<4>`|`comp::index_sequence<4>` and co, own implementation 267 | [N3656](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3656.htm)|make_unique|`std::make_unique()`|`comp::make_unique`, own implementation 268 | [N3654](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3654.html)|quoted|`ss >> std::quoted(str)`|no workaround, use boost 269 | [N3659](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3659.html)|shared_lock|`std::shared_lock`|no workaround 270 | [N3671](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3671.html)|two_range_algorithm|`std::equal(first1, last1, first2, last2)`|`comp::equal()`/`comp::mismatch()`/`comp::is_permutation()`, own implementation 271 | 272 | Get them all by specifying `cpp14_lib`. 273 | 274 | The following features are not and will never be supported: 275 | 276 | paper|description|reason 277 | -----|-----------|------ 278 | [N3668](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3669.pdf)|Fixing constexpr member functions without const|workaround not possible, just avoid relying on that behavior 279 | [N3670](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3670.htm)|Addressing Tuples by Type|just use index version 280 | [N3462](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3462.html)|std::result_of and SFINAE|impossible to check 281 | [N3545](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3545.html)|operator() for std::integral_constant|just "syntax" sugar 282 | [N3642](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3642.pdf)|UDl's for standard library|just "syntax" sugar 283 | [N3469](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3469.html)|Constexpr for std::chrono|no great workaround possible 284 | [N3470](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3470.html)|Constexpr for std::array|no great workaround possible 285 | [N3471](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3471.html)|Constexpr for utilities|no great workaround possible 286 | [N3657](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3657.html)|Heterogeneous lookup|optimization only, workaround for transparent functors supports this extension 287 | [N3655](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3655.pdf)|Alias templates for traits|just "syntax" sugar 288 | 289 | ### C++17 language features 290 | 291 | These features are all in the subdirectory `cpp17_lang`. 292 | 293 | paper|feature name|example|workaround, if any 294 | -----|------------|-------|------------------ 295 | [N4295](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4295.html)|fold_expressions|`return (args && ....);`|no workaround 296 | [N3928](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3928.pdf)|terse_static_assert|`static_assert(condition);`|`TERSE_STATIC_ASSERT(Cond)` macro 297 | [N4267](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4267.html)|utf8_char_literal|`char c = u8'A';`|`UTF8_ChAR_LITERAL(Str)` macro taking a normal string, appending `u8` prefix and converting it to a character 298 | 299 | ### C++17 library features \[up-to-date\] 300 | 301 | These features are all in the subdirectory `cpp17_lib`. 302 | 303 | paper|feature name|example|workaround, if any 304 | -----|------------|-------|------------------ 305 | [N4389](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4389.html)|bool_constant|`std::bool_constant`|`comp::bool_constant` 306 | [N4280](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4280.pdf)|container_access|`std::size(cont)`|`comp::size(cont)`, likewise for `std::empty()`/`std::data()` 307 | [N4169](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4169.html)|invoke|`std::invoke(f)`|`comp::invoke(f)` 308 | [N4279](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4279.html)|map_insertion|`m.try_emplace(key, value)`|`comp::try_emplace(m, key, value)`, likewise for `insert_or_assign()` 309 | [N4508](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4508.html)|shared_mutex|`std::shared_mutex`|no workaround 310 | [N4259](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4259.pdf)|uncaught_exceptions|`std::uncaught_exceptions()`|no workaround, note the plural! 311 | [N3911](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3911.pdf)|void_t|`std::void_t`|`comp::void_t` 312 | 313 | Get them all by specifying `cpp17_lib`. 314 | 315 | The following features are not and will never be supported: 316 | 317 | paper|description|reason 318 | -----|-----------|------ 319 | [N4190](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n34190.htm)|Removing deprecated things|removal, just don't use it 320 | [N4284](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4284)|Contiguous iterator|no actual code change 321 | [N4089](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4089.pdf)|Conversion for `std::unique_ptr`|difficult to check, avoid relying on behavior 322 | [N4277](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4277.html)|TriviallyCopyable `std::reference_wrapper`|difficult to check, avoid relying on behavior 323 | [N4258](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4258.pdf)|Cleaning-up `noexcept`|difficult to check, no big impact on user 324 | [N4266](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4266.html)|Missing SFINAE rule in `std::unique_ptr`|difficult to check, no big impact on code, avoid relying on behavior 325 | [N4387](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4387.html)|Improving constructor `std::pair` and `std::tuple`|difficult to check, avoid relying on behavior 326 | [N4510](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4510.html)|Minimal incomplete type support for containers|difficult to check, avoid relying on behavior 327 | 328 | ### Technical specifications 329 | 330 | The technical specifications for the C++ standard library. 331 | These features are all in the subdirectory `ts`. 332 | 333 | paper|feature name|description|workaround, if any 334 | -----|------------|-----------|------------------ 335 | [N3804](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3804.html)|any|`std::experimental::any` class|none, use boost or other implementation 336 | [N3915](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3915.pdf)|apply|`std::experimental::apply(f, tuple)`|`comp::apply()`, own implementation 337 | [N4273](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4273.htm)|container_erausre|`std::experimental::erase_if(vector, pred)`|`comp::erase_if()`/`comp::erase()`, own implementation 338 | [P0013R1](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/p0013r1.html)|logical_operator_traits|`std::experimental::disjunction`|`comp::conjunction`/`comp::disjunction`/`comp::negation`, own implementation 339 | [N4391](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2015/n4391.html)|make_array|`std::experimental::make_array()`|`comp::make_array()`/`comp::to_array()`, own implementation 340 | [N4076](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n4076.html)|not_fn|`std::experimental::not_fn()`|`comp::not_fn()`, own implementation 341 | [N3793](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3793.html)|optional|`std::experimental::optional`|none, use boost or other implementation 342 | [N3916](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3916.pdf)|pmr|Polymorphic memory resource|only `comp::memory_resource` base class 343 | [N3921](http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3921.html)|string_view|`std::experimental::string_view`| none, use other implementation 344 | 345 | Get them all by specifying `ts`. 346 | 347 | ### Environment 348 | 349 | Features regarding the general environment. These features are all in the subdirectory `env`. 350 | Note: These checks here aren't that great, it is recommended to set option explicitly. 351 | 352 | feature name|description|workaround, if any 353 | ------------|-------|------------------ 354 | exception_support|support for exception handling|`THROW(Ex)`, `RETHROW_EX`, fallback to `std::abort()`; `TRY`, fallback to `if (true)`, CATCH_ALL, fallback to `if (false)` 355 | hosted_implementation|freestanding vs hosted|alias macro `HOSTED_IMPLEMENTATION`, implementation of `std::swap()` and `std::move()`/`std::forward()` (if rvalue references are supported); those are otherwise not available 356 | rtti_support|support for RTTI|`comp::polymorhpic_cast`, fallback to `static_cast` 357 | threading_support|support for threading|no workaround 358 | 359 | Get them all by specifying `env`. 360 | 361 | ### Common extensions 362 | 363 | These features are all in the subdirectory `ext`. 364 | 365 | feature name|example|workaround, if any 366 | ------------|-------|------------------ 367 | assume|`__assume(cond)` (from MSVC)|`ASSUME(x)`, fallback to nothing 368 | bswap|`__builtin_bswap(x)` (from GCC)|``comp::bswap(x)` (for unsigned fixed-sized integers), fallback to manual swap (constexpr) 369 | clz|`__builtin_clz(x)` (from GCC)|`comp::clz(x)` (for unsigned fixed-sized integers), fallback to binary search (constexpr) 370 | counter|`__COUNTER__` (most compilers)|no workaround 371 | ctz|`__builtin_ctz(x)` (from GCC)|`comp::ctz(x)` (for unsigned integers), fallback to binary search (constexpr) 372 | expect|`__builtin_expect(x, val)` (from GCC)|`EXPECT(x, val)` (and `LIKELY(cond)`,`UNLIKELY(cond)`), fallback to value itself 373 | extension|`__extension__` (from GCC, marks extensions to silence warnings)|`EXTENSION`, fallback to nothing 374 | fallthrough|`[[clang::fallthrough]]` (from clang)|`FALLTHROUGH`, fallback to nothing 375 | has_include|`__has_include(header)`|`HAS_INCLUDE(x)`, fallback to always `0` 376 | int128|`__int128` (from GCC)|`comp::(u)int128_t`, no workaround, just convenience typedefs 377 | popcount|`__builtin_popcount(x)` (from GCC)|`comp::popcount(x)` (for unsigned integers), fallback to bithacks (constexpr) 378 | pretty_function|`__PRETTY_FUNCTION__` (from GCC)|`PRETTY_FUNCTION`, fallback to `__FUNCSIG__` on MSVC 379 | unreachable|`__builtin_unreachable()` (from GCC)|`UNREACHABLE`, fallback to `__assume(0)` under MSVC, otherwise nothing 380 | unused|`[[gnu::unused]]` (from GCC)|`UNUSED`, fallback to nothing; also `MAKE_UNUSED(expr)` that uses `(void)` trick 381 | 382 | Get them all by specifying `ext.cmake`. 383 | 384 | ## Contribution 385 | 386 | As you probably noted, there are features missing. 387 | I wrote this library in a few hours and concentrated on the most important features for me. 388 | If you want to extend it or improve a workaround, please don't hesitate to fork and PR 389 | (or just write an issue and let me take care of it, when I have time, if you're lazy). 390 | 391 | To write a new feature check, just create a new file in the appropriate subdirectory. 392 | Note: Do **not** include `comp_base.cmake!`. 393 | 394 | Inside the feature file you should only use the following CMake functions in the given order: 395 | 396 | 1. `comp_api_version(major[.minor[.patch]])` - checks if the API has the required version. `major` must match exactly, the rest not higher than the API version. If there is a version mismatch, it is an error. 397 | 398 | 2. `comp_feature( )` - does the feature check. 399 | `name` is the name of the feature without the directory, e.g. `constexpr`, not `cpp11_lang/constexpr`. 400 | `test_code` is the code that will be tested to see if the feature is supported. 401 | `standard` is the required C++ standard, this must be one of the `COMP_CPPXX_FLAG` values or `COMP_CPP98_FLAG` if no higher standard is needed. 402 | `required` is a list of requirede featuers that need to be supported in order to support this feature. If any of them isn't, this will not be checked. 403 | 404 | 3. `comp_workaround( )` - writes workaround code (optional). 405 | `name` must be the same as in `comp_feature()`. 406 | `workaround_code` is the workaround code itself. 407 | It must use `${COMP_PREFIX}` for macros and put anything else into the namespace `${COMP_NAMESPACE]` (variable expansion works there, so write it exactly like that). 408 | The result of the test is available through `${COMP_PREFIX}HAS_NAME`, e.g. `#if ${COMP_PREFIX}HAS_CONSTEXPR ... #else ... #endif`. 409 | `standard` is like in `comp_feature()` the standard required for the workaround code (the not-supported case, the supported case gets the standard of `comp_feature()`). 410 | `required` is a list of required features inside the workaround code. Their headers will be included prior to the workaround making it possible to use other workarounds. 411 | 412 | 4. `comp_sd6_macro( )` - writes SD 6 macro (optional, since 1.1). 413 | `name` must be the same as in `comp_feature()`. 414 | `sd6_name` is the SD-6 macro name and `value` its value. 415 | 416 | 5. `comp_unit_test( )` - defines a (Catch) unit test for the workaround code (optional). 417 | `name` must be the same as in `comp_feature()`. 418 | `global_code` will be put into the global namespace right after the including of the appropriate feature header and catch. 419 | `test_code` will be put into a Catch `TEST_CASE()`. 420 | 421 | The code for feature checking should be minimal and do not depend on any other advanced features (for example, do not use `auto` or `nullptr`) to prevent false failure. 422 | The workaround shouldn't use advanced features either, it can use other workarounds though. 423 | 424 | The testing code should test the workaround. It will be run by the testing framework for both modes, supported and not supported. 425 | 426 | Look at a few other files for example implementations. 427 | -------------------------------------------------------------------------------- /_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | cmake_minimum_required(VERSION 3.1) 6 | project(COMPATIBILITY_TEST) 7 | 8 | set(_COMP_TEST ${CMAKE_CURRENT_BINARY_DIR}/test) 9 | 10 | # download catch 11 | file(DOWNLOAD 12 | https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp 13 | ${_COMP_TEST}/catch.downloaded 14 | SHOW_PROGESS 15 | STATUS status 16 | LOG log) 17 | 18 | list(GET status 0 status_code) 19 | list(GET status 1 status_string) 20 | if((NOT EXISTS ${_COMP_TEST}/catch.hpp) AND (NOT status_code EQUAL 0)) 21 | message(FATAL_ERROR "error downloading catch: ${status_string}" 22 | "${log}") 23 | else() 24 | # succesful download, replace old catch.hpp 25 | file(RENAME ${_COMP_TEST}/catch.downloaded ${_COMP_TEST}/catch.hpp) 26 | endif() 27 | 28 | include(../comp_base.cmake) 29 | 30 | set(feature_names) 31 | file(GLOB features ${CMAKE_CURRENT_SOURCE_DIR}/../*/*.cmake) 32 | file(COPY main.cpp DESTINATION ${_COMP_TEST}) 33 | foreach(feature ${features}) 34 | get_filename_component(header "${feature}" NAME_WE) 35 | string(TOUPPER "${header}" macro_name) 36 | get_filename_component(dir "${feature}" DIRECTORY) 37 | string(FIND "${dir}" "/" last_sep REVERSE) 38 | math(EXPR last_sep "${last_sep} + 1") 39 | string(SUBSTRING "${dir}" ${last_sep} -1 dir) 40 | 41 | file(APPEND ${_COMP_TEST}/main.cpp "#include COMP_${macro_name}_HEADER\n") 42 | list(APPEND feature_names "${dir}/${header}") 43 | endforeach() 44 | 45 | add_library(_comp_test_runner INTERFACE) 46 | comp_target_features(_comp_test_runner INTERFACE ${feature_names} 47 | CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../ NOFLAGS) 48 | 49 | file(GLOB tests "${_COMP_TEST}/*.cpp") 50 | add_executable(comp_test "${tests}") 51 | comp_target_features(comp_test PRIVATE CPP17) 52 | target_link_libraries(comp_test PUBLIC _comp_test_runner) 53 | -------------------------------------------------------------------------------- /_test/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #define CATCH_CONFIG_COLOUR_NONE 3 | #include "catch.hpp" 4 | -------------------------------------------------------------------------------- /comp_base.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | # comp_base.cmake - base functionality for all compatibility files 6 | if(${CMAKE_MINIMUM_REQUIRED_VERSION} VERSION_LESS 3.0) 7 | message(FATAL_ERROR "compat requires CMake version 3.0+") 8 | endif() 9 | 10 | include(CheckCXXSourceCompiles) 11 | include(CheckCXXCompilerFlag) 12 | include(CMakeParseArguments) 13 | 14 | # EXTERNAL 15 | # the current API version 16 | set(COMP_API_VERSION 1.1 CACHE INTERNAL "compatibility api version" FORCE) 17 | 18 | set(COMP_REMOTE_REPO "foonathan/compatibility" CACHE STRING "Github Repository to pull from") 19 | set(COMP_REMOTE_BRANCH "master" CACHE STRING "Git branch on COMP_REMOTE_REPO") 20 | 21 | # EXTERNAL 22 | # download location for feature files, the feature file name will be appended 23 | # to circumvent download process, manually place the files at the CMAKE_PATH 24 | set(COMP_REMOTE_URL "https://raw.githubusercontent.com/${COMP_REMOTE_REPO}/${COMP_REMOTE_BRANCH}/" CACHE STRING "url of remote repository to be used for downloading the feature files") 25 | 26 | set(_COMP_LOG_LVL_DEBUG 3 CACHE INTERNAL "Logging Level: Debug") 27 | set(_COMP_LOG_LVL_INFO 2 CACHE INTERNAL "Logging Level: Info") 28 | set(_COMP_LOG_LVL_QUIET 1 CACHE INTERNAL "Logging Level: Quiet") 29 | set(_COMP_LOG_LVL_SILENT 0 CACHE INTERNAL "Logging Level: Silent") 30 | set(_COMP_LOG_LVL_ALL 100 CACHE INTERNAL "Logging Level: ALL") 31 | 32 | set(COMP_LOG_LEVEL "INFO" CACHE STRING "Default logging level used within all calls (default: INFO)") 33 | 34 | macro(_comp_adjust_log_level VARIABLE LEVEL) 35 | if(${LEVEL} MATCHES "(0|1|2|3|100)") 36 | set(${VARIABLE} ${LEVEL}) 37 | elseif(${LEVEL} MATCHES "(DEBUG|INFO|QUIET|SILENT|ALL)") 38 | set(${VARIABLE} ${_COMP_LOG_LVL_${VARIABLE}}) 39 | else() 40 | message(WARNING "Tried to set ${VARIABLE} to ${LEVEL}, defaulting to INFO.") 41 | comp_set_log_level(${VARIABLE} INFO) 42 | endif() 43 | endmacro() 44 | 45 | # External; Sets the `COMP_LOG_LEVEL` variable using either the `_COMP_LOG_LVL_XX` 46 | # variables or string versions. 47 | function(comp_set_log_level LEVEL) 48 | _comp_adjust_log_level(log_level ${LEVEL}) 49 | set(COMP_LOG_LEVEL ${log_level} CACHE STRING "Default logging level used within all calls (default: INFO)") 50 | endfunction() 51 | 52 | if(NOT COMP_LOG_LEVEL) 53 | comp_set_log_level(INFO) 54 | else() 55 | comp_set_log_level(${COMP_LOG_LEVEL}) 56 | endif() 57 | 58 | # Internal; 59 | # Log a message based on the current log level 60 | function(_comp_log level out_message) 61 | cmake_parse_arguments(log "EXACT" "" "" ${ARGN}) 62 | 63 | set(log off) 64 | if(NOT DEFINED COMP_LOG_LVL OR (${level} STREQUAL "ALL" OR COMP_LOG_LVL EQUAL ${_COMP_LOG_LVL_ALL})) 65 | set(log on) 66 | elseif(LOG_EXACT ) 67 | if(COMP_LOG_LVL EQUAL ${_COMP_LOG_LVL_${level}}) 68 | set(log on) 69 | endif() 70 | elseif(COMP_LOG_LVL GREATER ${_COMP_LOG_LVL_${level}} 71 | OR COMP_LOG_LVL EQUAL ${_COMP_LOG_LVL_${level}}) 72 | set(log on) 73 | endif() 74 | 75 | if(log) 76 | message(STATUS ${out_message}) 77 | endif() 78 | endfunction() 79 | 80 | # EXTERNAL; feature module 81 | # requires a certain API version 82 | function(comp_api_version version) 83 | string(FIND "${version}" "." first_dot) 84 | string(SUBSTRING "${version}" 0 ${first_dot} major_version) 85 | string(FIND "${COMP_API_VERSION}" "." first_dot) 86 | string(SUBSTRING "${COMP_API_VERSION}" 0 ${first_dot} comp_major_version) 87 | 88 | if(NOT major_version EQUAL comp_major_version OR COMP_API_VERSION VERSION_LESS version) 89 | message(FATAL_ERROR "compatibility version is ${COMP_API_VERSION}, required is ${version}") 90 | endif() 91 | endfunction() 92 | 93 | # INTERNAL 94 | # gets name, followed by flag, name, flag, name, flag... 95 | # checks flags in order of occurence 96 | # first matching flag will be used! 97 | # result is written into named cache option 98 | function(_comp_check_flags result standard_name) 99 | if(DEFINED ${result}) 100 | # If its defined, it likely means the library was included multiple times and we already 101 | # searched for it. 102 | return() 103 | endif() 104 | 105 | _comp_log(INFO "Checking flags for ${standard_name}") 106 | foreach(flag ${ARGN}) 107 | if(NOT DEFINED name) 108 | set(name ${flag}) 109 | else() 110 | set(CMAKE_REQUIRED_QUIET ON) 111 | check_cxx_compiler_flag("${flag}" ${name}) 112 | if(${name}) 113 | _comp_log(ALWAYS "Checking flags for ${standard_name} - Found: ${flag}") 114 | set(${result} ${flag} CACHE INTERNAL "Flag to activate ${standard_name}") 115 | return() 116 | elseif(MSVC) 117 | # MSVC < 2016 does *not* support the -std flag. 118 | if(NOT _COMP_MSVC_FLAG_${standard_name}_MSG_SHOWN) 119 | set(_COMP_MSVC_FLAG_${standard_name}_MSG_SHOWN TRUE CACHE INTERNAL '') 120 | _comp_log(INFO "Tried to check for ${standard_name}, but MSVC does not support flags.") 121 | endif() 122 | set(${result} "" CACHE INTERNAL "Flag to activate ${standard_name} (MSVC defaulted to ON)") 123 | return() 124 | endif() 125 | unset(name) 126 | endif() 127 | endforeach() 128 | message(WARNING "Checking flags for ${standard_name} - No required ${standard_name} flag found,\ 129 | this could either be the case or missing support for your compiler.") 130 | set(${result} "" CACHE INTERNAL "Flag to activate ${standard_name}") 131 | endfunction() 132 | 133 | set(COMP_CPP98_FLAG "" CACHE INTERNAL "Flag to activate C++98") 134 | _comp_check_flags(COMP_CPP11_FLAG "C++11" std_cpp11_flag -std=c++11 std_cpp0x_flag -std=c++0x) 135 | _comp_check_flags(COMP_CPP14_FLAG "C++14" std_cpp14_flag -std=c++14 std_cpp1y_flag -std=c++1y) 136 | _comp_check_flags(COMP_CPP17_FLAG "C++17" std_cpp17_flag -std=c++17 std_cpp1z_flag -std=c++1z) 137 | 138 | # INTERNAL 139 | # parses arguments for comp_compile_features 140 | macro(_comp_parse_arguments) 141 | cmake_parse_arguments(COMP "NOPREFIX;NO_HEADER_MACROS;CPP11;CPP14;CPP17;NOFLAGS" # no arg 142 | "PREFIX;NAMESPACE;CMAKE_PATH;INCLUDE_PATH;LOG;SINGLE_HEADER" # single arg 143 | "" ${ARGN}) 144 | if(COMP_NOPREFIX) 145 | set(COMP_PREFIX "") 146 | set(COMP_ID "") 147 | elseif(NOT DEFINED COMP_PREFIX) 148 | set(COMP_PREFIX "COMP_") 149 | set(COMP_ID "comp") 150 | elseif(${COMP_PREFIX} MATCHES "^.*_$") 151 | string(TOLOWER "${COMP_PREFIX}" COMP_ID) 152 | string(LENGTH "${COMP_ID}" length) 153 | math(EXPR length "${length} - 1") 154 | string(SUBSTRING "${COMP_ID}" 0 ${length} COMP_ID) 155 | else() 156 | string(TOLOWER "${COMP_PREFIX}" COMP_ID) 157 | endif() 158 | 159 | if(COMP_LOG) 160 | _comp_adjust_log_level(COMP_LOG ${COMP_LOG}) 161 | set(COMP_LOG_LVL ${COMP_LOG}) 162 | endif() 163 | 164 | if(NOT DEFINED COMP_LOG_LVL) 165 | set(COMP_LOG_LVL ${COMP_LOG_LEVEL}) 166 | endif() 167 | 168 | if(NOT DEFINED COMP_NAMESPACE) 169 | set(COMP_NAMESPACE "comp") 170 | endif() 171 | if(DEFINED _COMP_${COMP_ID}_namespace) 172 | if (NOT "${_COMP_${COMP_ID}_namespace}" STREQUAL "${COMP_NAMESPACE}") 173 | message(SEND_ERROR "Prefix ${COMP_PREFIX} already used with namespace name ${COMP_NAMESPACE} before") 174 | endif() 175 | else() 176 | set(_COMP_${COMP_ID}_namespace "${COMP_NAMESPACE}" CACHE INTERNAL "") 177 | endif() 178 | 179 | if(NOT DEFINED COMP_CMAKE_PATH) 180 | set(COMP_CMAKE_PATH "${CMAKE_BINARY_DIR}/comp.downloaded") 181 | endif() 182 | 183 | if(NOT DEFINED COMP_INCLUDE_PATH) 184 | set(COMP_INCLUDE_PATH "${CMAKE_BINARY_DIR}/comp.generated") 185 | endif() 186 | 187 | if(NOT DEFINED COMP_SINGLE_HEADER) 188 | set(COMP_SINGLE_HEADER off) 189 | endif() 190 | 191 | if(NOT DEFINED COMP_NO_HEADER_MACROS) 192 | set(COMP_NO_HEADER_MACROS off) 193 | endif() 194 | endmacro() 195 | 196 | # INTERNAL 197 | # translates feature names 198 | function(_comp_translate_feature feature) 199 | # Use a function so these don't bleed out of scope 200 | set(_cxx_alias_templates cpp11_lang/alias_template CACHE INTERNAL "") 201 | set(_cxx_alignas cpp11_lang/alignas CACHE INTERNAL "") 202 | set(_cxx_alignof cpp11_lang/alignof CACHE INTERNAL "") 203 | set(_cxx_attribute_deprecated cpp14_lang/deprecated CACHE INTERNAL "") 204 | set(_cxx_auto_type cpp11_lang/auto_type CACHE INTERNAL "") 205 | set(_cxx_constexpr cpp11_lang/constexpr CACHE INTERNAL "") 206 | set(_cxx_decltype cpp11_lang/decltype CACHE INTERNAL "") 207 | set(_cxx_decltype_auto cpp14_lang/return_type_deduction CACHE INTERNAL "") 208 | set(_cxx_deleted_functions cpp11_lang/delete_fnc CACHE INTERNAL "") 209 | set(_cxx_default_function_template_args cpp11_lang/default_function_template_args CACHE INTERNAL "") 210 | set(_cxx_explicit_conversions cpp11_lang/explicit_conversion_op CACHE INTERNAL "") 211 | set(_cxx_final cpp11_lang/final CACHE INTERNAL "") 212 | set(_cxx_lambdas cpp11_lang/lambdas CACHE INTERNAL "") 213 | set(_cxx_noexcept cpp11_lang/noexcept CACHE INTERNAL "") 214 | set(_cxx_nullptr cpp11_lang/nullptr CACHE INTERNAL "") 215 | set(_cxx_override cpp11_lang/override CACHE INTERNAL "") 216 | set(_cxx_relaxed_constexpr cpp14_lang/general_constexpr CACHE INTERNAL "") 217 | set(_cxx_range_for cpp11_lang/range_for CACHE INTERNAL "") 218 | set(_cxx_return_type_deduction cpp14_lang/return_type_deduction CACHE INTERNAL "") 219 | set(_cxx_right_angle_brackets cpp11_lang/right_angle_brackets CACHE INTERNAL "") 220 | set(_cxx_rvalue_references cpp11_lang/rvalue_ref CACHE INTERNAL "") 221 | set(_cxx_static_assert cpp11_lang/static_assert CACHE INTERNAL "") 222 | set(_cxx_strong_enums cpp11_lang/enum_class CACHE INTERNAL "") 223 | set(_cxx_thread_local cpp11_lang/thread_local CACHE INTERNAL "") 224 | set(_cxx_user_literals cpp11_lang/literal_op CACHE INTERNAL "") 225 | set(_cxx_variable_templates cpp14_lang/variable_template CACHE INTERNAL "") 226 | set(_cxx_variadic_templates cpp11_lang/parameter_pack CACHE INTERNAL "") 227 | 228 | # note: triple underscore at beginning! 229 | set(___cpp_alias_templates cpp11_lang/alias_template CACHE INTERNAL "") 230 | set(___cpp_constexpr cpp11_lang/constexpr CACHE INTERNAL "") 231 | set(___cpp_decltype cpp11_lang/decltype CACHE INTERNAL "") 232 | set(___cpp_user_defined_literals cpp11_lang/literal_op CACHE INTERNAL "") 233 | set(___cpp_noexcept cpp11_lang/noexcept CACHE INTERNAL "") 234 | set(___cpp_rvalue_references cpp11_lang/rvalue_ref CACHE INTERNAL "") 235 | set(___cpp_static_assert cpp11_lang/static_assert CACHE INTERNAL "") 236 | 237 | set(___cpp_return_type_deduction cpp14_lang/return_type_deduction CACHE INTERNAL "") 238 | set(___cpp_sized_deallocation cpp14_lang/sized_deallocation CACHE INTERNAL "") 239 | set(___cpp_variable_templates cpp14_lang/variable_template CACHE INTERNAL "") 240 | 241 | set(___cpp_lib_exchange_function cpp14_lib/exchange CACHE INTERNAL "") 242 | set(___cpp_lib_transparent_operators cpp14_lib/generic_operator_functors CACHE INTERNAL "") 243 | set(___cpp_lib_integer_sequence cpp14_lib/integer_sequence CACHE INTERNAL "") 244 | set(___cpp_lib_make_unique cpp14_lib/make_unique CACHE INTERNAL "") 245 | set(___cpp_lib_quoted_string_io cpp14_lib/quoted CACHE INTERNAL "") 246 | set(___cpp_lib_shared_timed_mutex cpp14_lib/shared_lock CACHE INTERNAL "") 247 | set(___cpp_lib_robust_nonmodifying_seq_ops cpp14_lib/two_range_algorithms CACHE INTERNAL "") 248 | 249 | set(___cpp_fold_expressions cpp17_lang/fold_expressions CACHE INTERNAL "") 250 | set(___cpp_unicode_characters cpp17_lang/utf8_char_literal CACHE INTERNAL "") 251 | 252 | set(___cpp_lib_nonmember_container_access cpp17_lib/container_access CACHE INTERNAL "") 253 | set(___cpp_lib_invoke cpp17_lib/invoke CACHE INTERNAL "") 254 | set(___cpp_lib_map_insertion cpp17_lib/map_insertion CACHE INTERNAL "") 255 | set(___cpp_lib_unordered_map_insertion cpp17_lib/map_insertion CACHE INTERNAL "") 256 | set(___cpp_lib_map_try_emplace cpp17_lib/map_insertion CACHE INTERNAL "") 257 | set(___cpp_lib_unordered_map_try_emplace cpp17_lib/map_insertion CACHE INTERNAL "") 258 | set(___cpp_lib_uncaught_exceptions cpp17_lib/uncaught_exceptions CACHE INTERNAL "") 259 | set(___cpp_lib_void_t cpp17_lib/void_t CACHE INTERNAL "") 260 | 261 | if(DEFINED _${feature}) 262 | set(feature "${_${feature}}" PARENT_SCOPE) 263 | elseif(${feature} MATCHES "cxx_*") 264 | message(WARNING "no compatibility option for CMake feature ${feature}") 265 | elseif(${feature} MATCHES "__cpp_*") 266 | message(WARNING "no compatibility option for SD-6 feature ${feature}") 267 | endif() 268 | endfunction() 269 | 270 | # INTERNAL 271 | # downloads the file for a feature 272 | function(_comp_fetch_feature path feature) 273 | if(NOT EXISTS "${path}/${feature}.cmake") 274 | if(${COMP_LOG_LVL} GREATER ${_COMP_LOG_LVL_INFO}) 275 | set(show_progress_flag "SHOW_PROGRESS") 276 | else() 277 | set(show_progress_flag "") 278 | endif() 279 | 280 | file(DOWNLOAD ${COMP_REMOTE_URL}${feature}.cmake 281 | ${path}/${feature}.cmake 282 | ${show_progress_flag} 283 | STATUS status 284 | LOG log) 285 | list(GET status 0 status_code) 286 | list(GET status 1 status_string) 287 | if(NOT status_code EQUAL 0) 288 | message(FATAL_ERROR "error downloading feature file ${feature}.cmake: ${status_string}. Check spelling of feature.\n${log}") 289 | endif() 290 | endif() 291 | endfunction() 292 | 293 | # INTERNAL 294 | # writes the header and testing code, if needed 295 | function(_comp_gen_files feature) 296 | get_filename_component(name "${feature}" NAME_WE) 297 | string(TOUPPER "${name}" macro_name) 298 | 299 | if (COMP_HAS_${macro_name}) 300 | set(result "1") 301 | else() 302 | set(result "0") 303 | endif() 304 | 305 | list(APPEND _COMP_HEADERS ${COMP_PREFIX}${macro_name}_HEADER="${COMP_INCLUDE_PATH}/${COMP_ID}/${name}.hpp") 306 | set(_COMP_HEADERS "${_COMP_HEADERS}" PARENT_SCOPE) 307 | 308 | file(WRITE ${COMP_INCLUDE_PATH}/${COMP_ID}/${name}.hpp 309 | "// This file was autogenerated using foonathan/compatibility. 310 | // See https://github.com/foonathan/compatibility for further information. 311 | // Do not edit manually! 312 | 313 | #ifndef COMP_${COMP_PREFIX}${macro_name}_HPP_INCLUDED 314 | #define COMP_${COMP_PREFIX}${macro_name}_HPP_INCLUDED 315 | 316 | #include 317 | 318 | #define ${COMP_PREFIX}HAS_${macro_name} ${result} 319 | 320 | ${${name}_sd6_macro} 321 | ${${name}_requires} 322 | ${${name}_workaround} 323 | 324 | #endif 325 | ") 326 | if(${name}_test_code) 327 | file(WRITE ${_COMP_TEST}/${name}.cpp 328 | "#define COMP_IN_PARENT_HEADER 329 | #include 330 | #include 331 | 332 | #include \"catch.hpp\" 333 | 334 | ${${name}_test_global} 335 | 336 | TEST_CASE(\"${name}\", \"\") 337 | { 338 | ${${name}_test_code} 339 | }") 340 | endif() 341 | endfunction() 342 | 343 | # INTERNAL 344 | # handles a feature file 345 | function(_comp_handle_feature feature) 346 | _comp_translate_feature(${feature}) 347 | _comp_fetch_feature(${COMP_CMAKE_PATH} ${feature}) 348 | include(${COMP_CMAKE_PATH}/${feature}.cmake) 349 | _comp_gen_files(${feature}) 350 | 351 | # propagate variables up 352 | set(_COMP_HEADERS "${_COMP_HEADERS}" PARENT_SCOPE) 353 | endfunction() 354 | 355 | # EXTERNAL; user 356 | # setups certain features for a target 357 | function(comp_target_features target include_policy) 358 | _comp_parse_arguments(${ARGN}) 359 | 360 | # these variables are modified/accessed by the feature modules 361 | # deprecated 362 | set(cpp11_flag ${COMP_CPP11_FLAG}) 363 | set(cpp14_flag ${COMP_CPP14_FLAG}) 364 | set(cpp17_flag ${COMP_CPP17_FLAG}) 365 | 366 | list(LENGTH COMP_UNPARSED_ARGUMENTS _args_len) 367 | _comp_log(QUIET "Checking ${_args_len} features" EXACT) 368 | foreach(feature ${COMP_UNPARSED_ARGUMENTS}) 369 | _comp_handle_feature(${feature}) 370 | endforeach() 371 | 372 | target_include_directories(${target} ${include_policy} $) 373 | 374 | if((NOT COMP_SINGLE_HEADER) AND (NOT COMP_NO_HEADER_MACROS)) 375 | target_compile_definitions(${target} ${include_policy} ${_COMP_HEADERS}) 376 | endif() 377 | 378 | # first explicit option, then implicit; 17 over 14 over 11 379 | if(COMP_CPP17) 380 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP17_FLAG} 381 | CACHE STRING "required compile options for target") 382 | elseif(COMP_CPP14) 383 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP14_FLAG} 384 | CACHE STRING "required compile options for target") 385 | elseif(COMP_CPP11) 386 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP14_FLAG} 387 | CACHE STRING "required compile options for target") 388 | elseif(need_COMP_CPP17_FLAG) 389 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP17_FLAG} 390 | CACHE STRING "required compile options for target") 391 | elseif(need_COMP_CPP14_FLAG) 392 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP14_FLAG} 393 | CACHE STRING "required compile options for target") 394 | elseif(need_COMP_CPP11_FLAG) 395 | set(${target}_COMP_COMPILE_OPTIONS ${COMP_CPP11_FLAG} 396 | CACHE STRING "required compile options for target") 397 | endif() 398 | 399 | # actually set option 400 | if (NOT COMP_NOFLAGS) 401 | target_compile_options(${target} PRIVATE ${${target}_COMP_COMPILE_OPTIONS}) 402 | endif() 403 | 404 | if(COMP_SINGLE_HEADER) 405 | set(include_lines ) 406 | foreach(header ${headers}) 407 | string(REGEX REPLACE ".+=\"(.+)\"" "\\1" header_path ${header}) 408 | file(RELATIVE_PATH header_path ${COMP_INCLUDE_PATH} ${header_path}) 409 | list(APPEND include_lines "#include \"${header_path}\"\n") 410 | endforeach() 411 | 412 | string(REPLACE ";" "" include_lines "${include_lines}") 413 | 414 | file(WRITE ${COMP_INCLUDE_PATH}/${COMP_ID}/${COMP_SINGLE_HEADER} 415 | "// This file was autogenerated using foonathan/compatibility. 416 | // See https://github.com/foonathan/compatibility for further information. 417 | // Do not edit manually! 418 | 419 | #ifndef COMP_${COMP_PREFIX}CONFIG_HPP_INCLUDED 420 | #define COMP_${COMP_PREFIX}CONFIG_HPP_INCLUDED 421 | 422 | ${include_lines} 423 | 424 | #endif") 425 | 426 | endif() 427 | 428 | list(LENGTH COMP_UNPARSED_ARGUMENTS _args_len) 429 | _comp_log(QUIET "Checking ${_args_len} features -- Completed" EXACT) 430 | endfunction() 431 | 432 | # EXTERNAL; feature module 433 | # checks for a feature with ${name} by compiling ${test_code} 434 | # standard is COMP_CPPXX_FLAG and will be used for testing 435 | # additional arguments are required other features, if they are not supported, it will be neither 436 | function(comp_feature name test_code standard) 437 | string(TOUPPER "${name}" macro_name) 438 | 439 | _comp_log(DEBUG "Checking for feature ${name}") 440 | 441 | if(_COMP_TEST_WORKAROUND) 442 | set(COMP_HAS_${macro_name} OFF CACHE INTERNAL "whether or not ${name} is available" FORCE) 443 | elseif(DEFINED COMP_HAS_${macro_name}) 444 | 445 | _comp_log(INFO "Checking for feature ${name} - overriden") 446 | 447 | if(COMP_HAS_${macro_name}) 448 | set(need_${standard} TRUE PARENT_SCOPE) 449 | endif() 450 | else() 451 | 452 | set(result ON) 453 | foreach(feature ${ARGN}) 454 | _comp_handle_feature(${feature}) 455 | get_filename_component(cur_name "${feature}" NAME_WE) 456 | string(TOUPPER "${cur_name}" cur_name) 457 | if(NOT COMP_HAS_${cur_name}) 458 | set(result OFF) 459 | _comp_log(ALL "Checking for feature ${name} - Requirement failure: ${feature}") 460 | endif() 461 | endforeach() 462 | 463 | if(result) 464 | set(CMAKE_REQUIRED_FLAGS "${${standard}}") 465 | set(CMAKE_REQUIRED_QUIET ON) 466 | check_cxx_source_compiles("${test_code}" has_${name}) 467 | 468 | if(has_${name}) 469 | set(COMP_HAS_${macro_name} ON CACHE INTERNAL "whether or not ${name} is available") 470 | set(need_${standard} TRUE PARENT_SCOPE) 471 | _comp_log(INFO "Checking for feature ${name} - overriden") 472 | else() 473 | set(COMP_HAS_${macro_name} OFF CACHE INTERNAL "whether or not ${name} is available") 474 | _comp_log(ALL "Checking for feature ${name} - Failed") 475 | endif() 476 | else() 477 | set(COMP_HAS_${macro_name} OFF CACHE INTERNAL "whether or not ${name} is available") 478 | endif() 479 | endif() 480 | endfunction() 481 | 482 | # EXTERNAL; feature module 483 | # writes workaround code 484 | # test result is available via macro ${COMP_PREFIX}HAS_${name in uppercase} 485 | # standard is COMP_CPPXX_FLAG required for the workaround code 486 | # if the test succeds, the standard of the test is also activated 487 | # additional arguments are required other features, their headers are also included then 488 | function(comp_workaround name workaround standard) 489 | set(${name}_workaround "${workaround}" PARENT_SCOPE) 490 | set(need_${standard} TRUE PARENT_SCOPE) 491 | set(requires "") 492 | foreach(feature ${ARGN}) 493 | get_filename_component(header "${feature}" NAME_WE) 494 | set(requires "${requires}#include \"${header}.hpp\"\n") 495 | _comp_handle_feature(${feature}) 496 | endforeach() 497 | 498 | # Parent vars 499 | set(${name}_requires ${requires} PARENT_SCOPE) 500 | set(_COMP_HEADERS "${_COMP_HEADERS}" PARENT_SCOPE) 501 | endfunction() 502 | 503 | # EXTERNAL; feature module 504 | # generates a unit test file for workaround of feature ${name} 505 | # the include for the feature is available as is the Catch library 506 | # ${code} will be placed inside a Catch TEST_CASE, ${global} in the global scope in front of it 507 | function(comp_unit_test name global code) 508 | if (NOT _COMP_TEST) 509 | return() 510 | endif() 511 | 512 | set(${name}_test_code "${code}" PARENT_SCOPE) 513 | set(${name}_test_global "${global}" PARENT_SCOPE) 514 | endfunction() 515 | 516 | # EXTERNAL; feature module 517 | # writes SD-6 feature macro with given name and value 518 | # overrides existing value if given one is greater or macro COMP_OVERRIDE_SD6 is defined 519 | function(comp_sd6_macro name sd6_name value) 520 | string(TOUPPER "${name}" macro_name) 521 | 522 | set(${name}_sd6_macro 523 | "${${name}_sd6_macro} 524 | #if ${COMP_PREFIX}HAS_${macro_name} 525 | #if !defined(${sd6_name}) 526 | #define ${sd6_name} ${value} 527 | #elif ${value} > ${sd6_name} 528 | #undef ${sd6_name} 529 | #define ${sd6_name} ${value} 530 | #elif defined(COMP_OVERRIDE_SD6) 531 | #undef ${sd6_name} 532 | #define ${sd6_name} ${value} 533 | #endif 534 | #endif" PARENT_SCOPE) 535 | endfunction() 536 | 537 | # EXTERNAL; umbrella feature module 538 | # downloads and includes a feature named ${feature} 539 | function(comp_fetch_include feature) 540 | _comp_fetch_feature(${COMP_CMAKE_PATH} ${feature}) 541 | include(${COMP_CMAKE_PATH}/${feature}.cmake) 542 | endfunction() 543 | 544 | # DEPRECATED, use comp_workaround 545 | macro(comp_gen_header name workaround) 546 | message(AUTHOR_WARNING "deprecated, use comp_workaround()") 547 | comp_workaround("${name}" "${workaround}" COMP_CPP98_FLAG) 548 | endmacro() 549 | 550 | # DEPRECATED, use comp_feature() 551 | macro(comp_check_feature code name) 552 | message(AUTHOR_WARNING "deprecated, use comp_feature()") 553 | string(FIND "${ARGN}" "${cpp17_flag}" res) 554 | if (NOT (res EQUAL -1)) 555 | comp_feature(${name} ${code} COMP_CPP17_FLAG) 556 | else() 557 | string(FIND "${ARGN}" "${cpp14_flag}" res) 558 | if(NOT (res EQUAL -1)) 559 | comp_feature(${name} ${code} COMP_CPP14_FLAG) 560 | else() 561 | string(FIND "${ARGN}" "${cpp11_flag}" res) 562 | if(NOT (res EQUAL -1)) 563 | comp_feature(${name} ${code} COMP_CPP11_FLAG) 564 | else() 565 | comp_feature(${name} ${code} COMP_CPP98_FLAG) 566 | endif() 567 | endif() 568 | endif() 569 | endmacro() 570 | -------------------------------------------------------------------------------- /cpp11_lang.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp11_lang/alias_template) 6 | comp_fetch_include(cpp11_lang/alignas) 7 | comp_fetch_include(cpp11_lang/alignof) 8 | comp_fetch_include(cpp11_lang/auto_type) 9 | comp_fetch_include(cpp11_lang/constexpr) 10 | comp_fetch_include(cpp11_lang/decltype) 11 | comp_fetch_include(cpp11_lang/default_function_template_args) 12 | comp_fetch_include(cpp11_lang/delete_fnc) 13 | comp_fetch_include(cpp11_lang/enum_class) 14 | comp_fetch_include(cpp11_lang/explicit_conversion_op) 15 | comp_fetch_include(cpp11_lang/final) 16 | comp_fetch_include(cpp11_lang/inline_namespace) 17 | comp_fetch_include(cpp11_lang/lambdas) 18 | comp_fetch_include(cpp11_lang/literal_op) 19 | comp_fetch_include(cpp11_lang/noexcept) 20 | comp_fetch_include(cpp11_lang/noreturn) 21 | comp_fetch_include(cpp11_lang/nullptr) 22 | comp_fetch_include(cpp11_lang/override) 23 | comp_fetch_include(cpp11_lang/parameter_pack) 24 | comp_fetch_include(cpp11_lang/range_for) 25 | comp_fetch_include(cpp11_lang/right_angle_brackets) 26 | comp_fetch_include(cpp11_lang/rvalue_ref) 27 | comp_fetch_include(cpp11_lang/static_assert) 28 | comp_fetch_include(cpp11_lang/thread_local) 29 | -------------------------------------------------------------------------------- /cpp11_lang/alias_template.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(alias_template 11 | "template struct foo {}; 12 | template using bar = foo; 13 | int main(){}" 14 | COMP_CPP11_FLAG) 15 | 16 | if(COMP_API_VERSION VERSION_GREATER 1.0) 17 | comp_sd6_macro(alias_template __cpp_alias_template 200704) 18 | endif() 19 | -------------------------------------------------------------------------------- /cpp11_lang/alignas.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(alignas "int main() {alignas(int) char c; alignas(16) int i;}" COMP_CPP11_FLAG) 11 | comp_workaround(alignas " 12 | #ifndef ${COMP_PREFIX}ALIGNAS 13 | #if ${COMP_PREFIX}HAS_ALIGNAS 14 | #define ${COMP_PREFIX}ALIGNAS(X) alignas(X) 15 | #elif defined(_MSC_VER) 16 | #define ${COMP_PREFIX}ALIGNAS(X) __declspec(align(X)) 17 | #elif defined(__GNUC__) 18 | #define ${COMP_PREFIX}ALIGNAS(X) __attribute__((__aligned__(X))) 19 | #else 20 | #error \"no alignas replacement available\" 21 | #endif 22 | #endif" COMP_CPP98_FLAG) 23 | -------------------------------------------------------------------------------- /cpp11_lang/alignof.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(alignof "int main() {int i = alignof(int);}" COMP_CPP11_FLAG) 11 | comp_workaround(alignof 12 | " 13 | #ifndef ${COMP_PREFIX}ALIGNOF 14 | #if ${COMP_PREFIX}HAS_ALIGNOF 15 | #define ${COMP_PREFIX}ALIGNOF(x) alignof(x) 16 | #elif defined(_MSC_VER) 17 | #define ${COMP_PREFIX}ALIGNOF(x) __alignof(x) 18 | #elif defined(__GNUC__) 19 | #define ${COMP_PREFIX}ALIGNOF(x) __alignof__(x) 20 | #else 21 | #error \"no alignof replacement available\" 22 | #endif 23 | #endif 24 | " COMP_CPP98_FLAG) -------------------------------------------------------------------------------- /cpp11_lang/auto_type.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(auto_type "int main() {auto i = 0.f;}" COMP_CPP11_FLAG) -------------------------------------------------------------------------------- /cpp11_lang/constexpr.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(constexpr "int main() {constexpr int foo = 1;}" COMP_CPP11_FLAG) 11 | comp_workaround(constexpr 12 | "#ifndef ${COMP_PREFIX}CONSTEXPR 13 | #if ${COMP_PREFIX}HAS_CONSTEXPR 14 | #define ${COMP_PREFIX}CONSTEXPR constexpr 15 | #else 16 | #define ${COMP_PREFIX}CONSTEXPR const 17 | #endif 18 | #endif 19 | 20 | #ifndef ${COMP_PREFIX}CONSTEXPR_FNC 21 | #if ${COMP_PREFIX}HAS_CONSTEXPR 22 | #define ${COMP_PREFIX}CONSTEXPR_FNC constexpr 23 | #else 24 | #define ${COMP_PREFIX}CONSTEXPR_FNC inline 25 | #endif 26 | #endif" COMP_CPP98_FLAG) 27 | 28 | if(COMP_API_VERSION VERSION_GREATER 1.0) 29 | comp_sd6_macro(constexpr __cpp_constexpr 200704) 30 | endif() 31 | -------------------------------------------------------------------------------- /cpp11_lang/decltype.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(decltype "int main() {int i; decltype(i) j;}" COMP_CPP11_FLAG) 11 | comp_workaround(decltype 12 | " 13 | #ifndef ${COMP_PREFIX}DECLTYPE 14 | #if ${COMP_PREFIX}HAS_DECLTYPE 15 | #define ${COMP_PREFIX}DECLTYPE(x) decltype(x) 16 | #elif defined(__GNUC__) 17 | #define ${COMP_PREFIX}DECLTYPE(X) __typeof__(x) 18 | #else 19 | #error \"no decltype replacement available\" 20 | #endif 21 | #endif" COMP_CPP98_FLAG) 22 | 23 | if(COMP_API_VERSION VERSION_GREATER 1.0) 24 | comp_sd6_macro(decltype __cpp_decltype 200707) 25 | endif() 26 | -------------------------------------------------------------------------------- /cpp11_lang/default_function_template_args.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # Taken from: 11 | # http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 12 | comp_feature(default_function_template_args 13 | "template 14 | void f(T t = 0, U u = 0) 15 | { (void)t; (void) u; } 16 | 17 | int main() 18 | { 19 | f(1, 'c'); // f(1,'c') 20 | f(1); // f(1,0) 21 | // f(); // error: T cannot be deduced 22 | f(); // f(0,0) 23 | f(); // f(0,0) 24 | return 0; 25 | }" COMP_CPP11_FLAG) 26 | -------------------------------------------------------------------------------- /cpp11_lang/delete_fnc.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(delete_fnc "struct foo { foo(const foo&) = delete; }; 11 | int main(){}" COMP_CPP11_FLAG) 12 | -------------------------------------------------------------------------------- /cpp11_lang/enum_class.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(enum_class "enum class Colour: unsigned int { Red = 1, Blue = 3 }; 11 | int main() { const Colour c = Colour::Red; }" COMP_CPP11_FLAG) -------------------------------------------------------------------------------- /cpp11_lang/explicit_conversion_op.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(explicit_conversion_op 11 | "struct foo 12 | { 13 | explicit operator int() {return 5;} 14 | explicit operator bool() {return true;} 15 | }; 16 | int main() 17 | { 18 | foo f; 19 | int i = static_cast(f); 20 | bool b = static_cast(f); 21 | if (f) {} 22 | }" COMP_CPP11_FLAG) -------------------------------------------------------------------------------- /cpp11_lang/final.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(final "struct base {virtual void foo() {}}; 11 | struct derived final : base {void foo() final {}}; 12 | int main(){}" COMP_CPP11_FLAG) 13 | comp_workaround(final 14 | "#ifndef ${COMP_PREFIX}FINAL 15 | #if ${COMP_PREFIX}HAS_FINAL 16 | #define ${COMP_PREFIX}FINAL final 17 | #else 18 | #define ${COMP_PREFIX}FINAL 19 | #endif 20 | #endif" COMP_CPP98_FLAG) 21 | -------------------------------------------------------------------------------- /cpp11_lang/inline_namespace.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(inline_namespace 11 | "inline namespace foo {} 12 | int main(){}" 13 | COMP_CPP11_FLAG) 14 | -------------------------------------------------------------------------------- /cpp11_lang/lambdas.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # Taken from: 11 | # http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 12 | comp_feature(lambdas 13 | "#include 14 | #include 15 | void abssort(float *x, unsigned N) { 16 | std::sort(x, x+N, 17 | [](float a, float b) { 18 | return std::abs(a) < std::abs(b); 19 | }); 20 | } 21 | 22 | int main() 23 | { 24 | float* arr = new float[20]; 25 | abssort(arr, 20); 26 | } 27 | " COMP_CPP11_FLAG) 28 | -------------------------------------------------------------------------------- /cpp11_lang/literal_op.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(literal_op "#include 11 | int operator\"\" _foo(const char *, std::size_t){return 0;} int main(){}" 12 | COMP_CPP11_FLAG) 13 | 14 | if(COMP_API_VERSION VERSION_GREATER 1.0) 15 | comp_sd6_macro(literal_op __cpp_user_defined_literals 200809) 16 | endif() 17 | -------------------------------------------------------------------------------- /cpp11_lang/noexcept.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(noexcept "void foo() noexcept {} int main(){}" COMP_CPP11_FLAG) 11 | comp_workaround(noexcept 12 | "#ifndef ${COMP_PREFIX}NOEXCEPT 13 | #if ${COMP_PREFIX}HAS_NOEXCEPT 14 | #define ${COMP_PREFIX}NOEXCEPT noexcept 15 | #else 16 | #define ${COMP_PREFIX}NOEXCEPT 17 | #endif 18 | #endif 19 | 20 | #ifndef ${COMP_PREFIX}NOEXCEPT_IF 21 | #if ${COMP_PREFIX}HAS_NOEXCEPT 22 | #define ${COMP_PREFIX}NOEXCEPT_IF(x) noexcept(x) 23 | #else 24 | #define ${COMP_PREFIX}NOEXCEPT_IF(x) 25 | #endif 26 | #endif 27 | 28 | #ifndef ${COMP_PREFIX}NOEXCEPT_OP 29 | #if ${COMP_PREFIX}HAS_NOEXCEPT 30 | #define ${COMP_PREFIX}NOEXCEPT_OP(x) noexcept(x) 31 | #else 32 | #define ${COMP_PREFIX}NOEXCEPT_OP(x) false 33 | #endif 34 | #endif" COMP_CPP98_FLAG) 35 | 36 | if(COMP_API_VERSION VERSION_GREATER 1.0) 37 | comp_sd6_macro(noexcept __cpp_noexcept 201003) 38 | endif() 39 | -------------------------------------------------------------------------------- /cpp11_lang/noreturn.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(noreturn "[[noreturn]] int f(); int main() {}" COMP_CPP11_FLAG) 11 | comp_workaround(noreturn 12 | "#ifndef ${COMP_PREFIX}NORETURN 13 | #if ${COMP_PREFIX}HAS_NORETURN 14 | #define ${COMP_PREFIX}NORETURN [[noreturn]] 15 | #elif defined(__GNUC__) 16 | #define ${COMP_PREFIX}NORETURN __attribute__((noreturn)) 17 | #elif defined(_MSC_VER) 18 | #define ${COMP_PREFIX}NORETURN __declspec(noreturn) 19 | #else 20 | #define ${COMP_PREFIX}NORETURN 21 | #endif 22 | #endif" COMP_CPP98_FLAG) -------------------------------------------------------------------------------- /cpp11_lang/nullptr.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(nullptr "int main(){void *ptr = nullptr;}" COMP_CPP11_FLAG) 11 | comp_workaround(nullptr 12 | "#ifndef ${COMP_PREFIX}NULLPTR 13 | #if ${COMP_PREFIX}HAS_NULLPTR 14 | #define ${COMP_PREFIX}NULLPTR nullptr 15 | 16 | namespace ${COMP_NAMESPACE} 17 | { 18 | typedef std::nullptr_t nullptr_t; 19 | } 20 | #else 21 | namespace ${COMP_NAMESPACE} 22 | { 23 | class nullptr_t 24 | { 25 | public: 26 | template 27 | inline operator T*() const 28 | { return 0; } 29 | 30 | template 31 | inline operator T C::*() const 32 | { return 0; } 33 | 34 | private: 35 | void operator&() const; 36 | }; 37 | } 38 | 39 | #define ${COMP_PREFIX}NULLPTR ${COMP_NAMESPACE}::nullptr_t() 40 | #endif 41 | #endif" COMP_CPP98_FLAG) 42 | comp_unit_test(nullptr 43 | " 44 | struct nullptr_foo 45 | { 46 | int m; 47 | 48 | void foo() {} 49 | }; 50 | " 51 | " 52 | ${COMP_NAMESPACE}::nullptr_t nptr = ${COMP_PREFIX}NULLPTR; 53 | void* vptr = ${COMP_PREFIX}NULLPTR; 54 | int* iptr = ${COMP_PREFIX}NULLPTR; 55 | int nullptr_foo::*mptr = ${COMP_PREFIX}NULLPTR; 56 | void (nullptr_foo::*mfptr)() = ${COMP_PREFIX}NULLPTR; 57 | 58 | REQUIRE(!vptr); 59 | REQUIRE(!iptr); 60 | REQUIRE(!mptr); 61 | REQUIRE(!mfptr); 62 | ") -------------------------------------------------------------------------------- /cpp11_lang/override.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(override "struct base {virtual void foo() {}}; 11 | struct derived : base {void foo() override {}}; 12 | int main(){}" COMP_CPP11_FLAG) 13 | comp_workaround(override 14 | "#ifndef ${COMP_PREFIX}OVERRIDE 15 | #if ${COMP_PREFIX}HAS_OVERRIDE 16 | #define ${COMP_PREFIX}OVERRIDE override 17 | #else 18 | #define ${COMP_PREFIX}OVERRIDE 19 | #endif 20 | #endif" COMP_CPP98_FLAG) 21 | -------------------------------------------------------------------------------- /cpp11_lang/parameter_pack.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(parameter_pack "template 11 | void f(const Tn&... args); 12 | 13 | template 14 | void f(const T& t, const Tn&... rest) 15 | { (void)t; f(rest...); } 16 | 17 | template <> 18 | void f() 19 | { } 20 | 21 | int main() 22 | { f(1, 2); f(\"one\", 2); f(1); f(); } 23 | " COMP_CPP11_FLAG) 24 | 25 | -------------------------------------------------------------------------------- /cpp11_lang/range_for.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(range_for "int main() 11 | { 12 | int array[3] = { 1, 2, 3 }; 13 | for (int& x : array) 14 | x *= 2; 15 | }" COMP_CPP11_FLAG) 16 | 17 | -------------------------------------------------------------------------------- /cpp11_lang/right_angle_brackets.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(right_angle_brackets "#include 11 | typedef std::vector > Table; // OK 12 | typedef std::vector> Flags; // OK (Error < CPP11) 13 | int main(){}" COMP_CPP11_FLAG) 14 | 15 | -------------------------------------------------------------------------------- /cpp11_lang/rvalue_ref.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(rvalue_ref "int main(){int&& rvalue = 5;}" COMP_CPP11_FLAG) 11 | 12 | if(COMP_API_VERSION VERSION_GREATER 1.0) 13 | comp_sd6_macro(rvalue_ref __cpp_rvalue_references 200610) 14 | endif() 15 | -------------------------------------------------------------------------------- /cpp11_lang/static_assert.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(static_assert "int main(){static_assert(true, \"\");}" COMP_CPP11_FLAG) 11 | comp_workaround(static_assert 12 | "#ifndef ${COMP_PREFIX}STATIC_ASSERT 13 | #if ${COMP_PREFIX}HAS_STATIC_ASSERT 14 | #define ${COMP_PREFIX}STATIC_ASSERT(Expr, Msg) static_assert(Expr, Msg) 15 | #else 16 | namespace ${COMP_NAMESPACE} { namespace detail 17 | { 18 | template 19 | struct static_assert_impl; 20 | 21 | template <> 22 | struct static_assert_impl {}; 23 | }} // namespace ${COMP_NAMESPACE}::detail 24 | 25 | #define ${COMP_PREFIX}STATIC_ASSERT(Expr, Msg) ${COMP_NAMESPACE}::detail::static_assert_impl<(Expr)>() 26 | #endif 27 | #endif" COMP_CPP98_FLAG) 28 | 29 | if(COMP_API_VERSION VERSION_GREATER 1.0) 30 | comp_sd6_macro(static_assert __cpp_static_assert 200410) 31 | endif() 32 | -------------------------------------------------------------------------------- /cpp11_lang/thread_local.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(thread_local "thread_local int i; int main() {auto ptr = &i;}" COMP_CPP11_FLAG) 11 | comp_workaround(thread_local 12 | "#ifndef ${COMP_PREFIX}THREAD_LOCAL 13 | #if ${COMP_PREFIX}HAS_THREAD_LOCAL 14 | #define ${COMP_PREFIX}THREAD_LOCAL thread_local 15 | #elif defined(__GNUC__) 16 | #define ${COMP_PREFIX}THREAD_LOCAL __thread 17 | #elif defined(_MSC_VER) 18 | #define ${COMP_PREFIX}THREAD_LOCAL __declspec(thread) 19 | #else 20 | #error \"no thread_local replacement available\" 21 | #endif 22 | #endif" COMP_CPP98_FLAG) 23 | -------------------------------------------------------------------------------- /cpp11_lib.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp11_lib/get_new_handler) 6 | comp_fetch_include(cpp11_lib/get_terminate) 7 | comp_fetch_include(cpp11_lib/is_trivially) 8 | comp_fetch_include(cpp11_lib/max_align_t) 9 | comp_fetch_include(cpp11_lib/mutex) 10 | comp_fetch_include(cpp11_lib/to_string) 11 | -------------------------------------------------------------------------------- /cpp11_lib/get_new_handler.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(get_new_handler "#include 11 | int main() {std::new_handler handler = std::get_new_handler();}" 12 | COMP_CPP11_FLAG) 13 | comp_workaround(get_new_handler 14 | "#include 15 | 16 | namespace ${COMP_NAMESPACE} 17 | { 18 | #if ${COMP_PREFIX}HAS_GET_NEW_HANDLER 19 | inline std::new_handler get_new_handler() 20 | { 21 | return std::get_new_handler(); 22 | } 23 | #else 24 | inline std::new_handler get_new_handler() 25 | { 26 | std::new_handler h = std::set_new_handler(0); 27 | std::set_new_handler(h); 28 | return h; 29 | } 30 | #endif 31 | }" COMP_CPP98_FLAG) 32 | -------------------------------------------------------------------------------- /cpp11_lib/get_terminate.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(get_terminate "#include 11 | int main() {std::terminate_handler handler = std::get_terminate();}" 12 | COMP_CPP11_FLAG) 13 | comp_workaround(get_terminate 14 | "#include 15 | 16 | namespace ${COMP_NAMESPACE} 17 | { 18 | #if ${COMP_PREFIX}HAS_GET_TERMINATE 19 | inline std::terminate_handler get_terminate() 20 | { 21 | return std::get_terminate(); 22 | } 23 | #else 24 | inline std::terminate_handler get_terminate() 25 | { 26 | std::terminate_handler h = std::set_terminate(0); 27 | std::set_terminate(h); 28 | return h; 29 | } 30 | #endif 31 | }" COMP_CPP98_FLAG) -------------------------------------------------------------------------------- /cpp11_lib/is_trivially.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # the is_trivially_XXX traits were missing under some libstdc++ versions 11 | # is_trivial was available though 12 | comp_feature(is_trivially "#include 13 | int main() 14 | { 15 | int a = std::is_trivially_copyable::value; 16 | }" COMP_CPP11_FLAG) 17 | comp_workaround(is_trivially 18 | "#include 19 | 20 | namespace ${COMP_NAMESPACE} 21 | { 22 | #if ${COMP_PREFIX}HAS_IS_TRIVIALLY 23 | using std::is_trivially_copyable; 24 | 25 | using std::is_trivially_constructible; 26 | using std::is_trivially_default_constructible; 27 | using std::is_trivially_copy_constructible; 28 | using std::is_trivially_move_constructible; 29 | 30 | using std::is_trivially_assignable; 31 | using std::is_trivially_copy_assignable; 32 | using std::is_trivially_move_assignable; 33 | 34 | using std::is_trivially_destructible; 35 | #else 36 | template 37 | struct is_trivially_copyable 38 | : std::integral_constant::value> {}; 39 | 40 | template 41 | struct is_trivially_constructible 42 | : std::integral_constant::value 43 | && std::is_trivial::type>::value> {}; 44 | 45 | template 46 | struct is_trivially_default_constructible 47 | : std::integral_constant::value 48 | && std::is_trivial::type>::value> {}; 49 | 50 | template 51 | struct is_trivially_copy_constructible 52 | : std::integral_constant::value 53 | && std::is_trivial::type>::value> {}; 54 | 55 | template 56 | struct is_trivially_move_constructible 57 | : std::integral_constant::value 58 | && std::is_trivial::type>::value> {}; 59 | 60 | template 61 | struct is_trivially_assignable 62 | : std::integral_constant::value 63 | && std::is_trivial::type>::value> {}; 64 | 65 | template 66 | struct is_trivially_copy_assignable 67 | : std::integral_constant::value 68 | && std::is_trivial::type>::value> {}; 69 | 70 | template 71 | struct is_trivially_move_assignable 72 | : std::integral_constant::value 73 | && std::is_trivial::type>::value> {}; 74 | 75 | template 76 | struct is_trivially_destructible 77 | : std::integral_constant::value 78 | && std::is_trivial::type>::value> {}; 79 | #endif 80 | }" COMP_CPP11_FLAG) 81 | 82 | comp_unit_test(is_trivially 83 | "" 84 | " 85 | using namespace ${COMP_NAMESPACE}; 86 | 87 | // just instantiations 88 | static_assert(is_trivially_copyable::value, \"\"); 89 | 90 | static_assert(is_trivially_constructible::value, \"\"); 91 | static_assert(is_trivially_default_constructible::value, \"\"); 92 | static_assert(is_trivially_move_constructible::value, \"\"); 93 | static_assert(is_trivially_copy_constructible::value, \"\"); 94 | 95 | static_assert(is_trivially_assignable::value, \"\"); 96 | static_assert(is_trivially_copy_assignable::value, \"\"); 97 | static_assert(is_trivially_move_assignable::value, \"\"); 98 | 99 | static_assert(is_trivially_destructible::value, \"\"); 100 | ") 101 | -------------------------------------------------------------------------------- /cpp11_lib/max_align_t.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # note: using namespace std; important here, as it might not be in namespace std 11 | comp_feature(max_align_t "#include 12 | using namespace std; 13 | int main() {max_align_t val;}" COMP_CPP11_FLAG) 14 | comp_workaround(max_align_t 15 | "namespace ${COMP_NAMESPACE} 16 | { 17 | #if ${COMP_PREFIX}HAS_MAX_ALIGN_T 18 | namespace max_align 19 | { 20 | using namespace std; // might not be in namespace std 21 | typedef max_align_t type; 22 | } 23 | 24 | typedef max_align::type max_align_t; 25 | #else 26 | // this struct should have maximum alignment 27 | struct max_align_t 28 | { 29 | long double ld; 30 | long long ll; 31 | }; 32 | #endif 33 | }" COMP_CPP98_FLAG) 34 | -------------------------------------------------------------------------------- /cpp11_lib/mutex.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(mutex "#include 11 | int main() 12 | { 13 | std::mutex m1, m2; 14 | std::lock_guard a(m1); 15 | std::unique_lock b(m2); 16 | }" COMP_CPP11_FLAG) 17 | -------------------------------------------------------------------------------- /cpp11_lib/to_string.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(to_string "#include 11 | int main() 12 | { 13 | std::to_string(5); 14 | std::to_string(5ul); 15 | std::to_string(5.0); 16 | }" COMP_CPP11_FLAG) 17 | comp_workaround(to_string 18 | "#include 19 | 20 | #if !${COMP_PREFIX}HAS_TO_STRING 21 | #include 22 | #include 23 | #endif 24 | 25 | namespace ${COMP_NAMESPACE} 26 | { 27 | #if ${COMP_PREFIX}HAS_TO_STRING 28 | using std::to_string; 29 | #else 30 | inline std::string to_string(int value) 31 | { 32 | char buf[4 * sizeof(value)]; 33 | std::sprintf(buf, \"%d\", value); 34 | return buf; 35 | } 36 | 37 | inline std::string to_string(long value) 38 | { 39 | char buf[4 * sizeof(value)]; 40 | std::sprintf(buf, \"%ld\", value); 41 | return buf; 42 | } 43 | 44 | inline std::string to_string(long long value) 45 | { 46 | char buf[4 * sizeof(value)]; 47 | std::sprintf(buf, \"%lld\", value); 48 | return buf; 49 | } 50 | 51 | inline std::string to_string(unsigned value) 52 | { 53 | char buf[4 * sizeof(value)]; 54 | std::sprintf(buf, \"%u\", value); 55 | return buf; 56 | } 57 | 58 | inline std::string to_string(unsigned long value) 59 | { 60 | char buf[4 * sizeof(value)]; 61 | std::sprintf(buf, \"%lu\", value); 62 | return buf; 63 | } 64 | 65 | inline std::string to_string(unsigned long long value) 66 | { 67 | char buf[4 * sizeof(value)]; 68 | std::sprintf(buf, \"%llu\", value); 69 | return buf; 70 | } 71 | 72 | inline std::string to_string(float value) 73 | { 74 | char buf[FLT_MAX_10_EXP + 20]; 75 | std::sprintf(buf, \"%f\", value); 76 | return buf; 77 | } 78 | 79 | inline std::string to_string(double value) 80 | { 81 | char buf[DBL_MAX_10_EXP + 20]; 82 | std::sprintf(buf, \"%f\", value); 83 | return buf; 84 | } 85 | 86 | inline std::string to_string(long double value) 87 | { 88 | char buf[LDBL_MAX_10_EXP + 20]; 89 | std::sprintf(buf, \"%Lf\", value); 90 | return buf; 91 | } 92 | #endif 93 | }" COMP_CPP98_FLAG) 94 | comp_unit_test(to_string 95 | " 96 | #include 97 | 98 | template 99 | void test_integer() 100 | { 101 | auto min = std::numeric_limits::min(); 102 | auto max = std::numeric_limits::max(); 103 | 104 | REQUIRE(${COMP_NAMESPACE}::to_string(Int(0)) == \"0\"); 105 | REQUIRE(${COMP_NAMESPACE}::to_string(Int(1024)) == \"1024\"); 106 | REQUIRE(${COMP_NAMESPACE}::to_string(Int(-10)) == \"-10\"); 107 | 108 | REQUIRE(${COMP_NAMESPACE}::to_string(min) != \"\"); 109 | REQUIRE(${COMP_NAMESPACE}::to_string(max) != \"\"); 110 | } 111 | 112 | template 113 | void test_unsigned_integer() 114 | { 115 | auto max = std::numeric_limits::max(); 116 | 117 | REQUIRE(${COMP_NAMESPACE}::to_string(Int(0)) == \"0\"); 118 | REQUIRE(${COMP_NAMESPACE}::to_string(Int(1024)) == \"1024\"); 119 | 120 | REQUIRE(${COMP_NAMESPACE}::to_string(max) != \"\"); 121 | } 122 | 123 | template 124 | void test_float() 125 | { 126 | auto min = std::numeric_limits::min(); 127 | auto max = std::numeric_limits::max(); 128 | auto inf = std::numeric_limits::infinity(); 129 | auto nan = std::numeric_limits::quiet_NaN(); 130 | 131 | REQUIRE(${COMP_NAMESPACE}::to_string(Float(0)) == \"0.000000\"); 132 | REQUIRE(${COMP_NAMESPACE}::to_string(Float(1024)) == \"1024.000000\"); 133 | REQUIRE(${COMP_NAMESPACE}::to_string(Float(0.5)) == \"0.500000\"); 134 | REQUIRE(${COMP_NAMESPACE}::to_string(Float(-0.5)) == \"-0.500000\"); 135 | REQUIRE(${COMP_NAMESPACE}::to_string(Float(-10)) == \"-10.000000\"); 136 | 137 | auto inf_str = ${COMP_NAMESPACE}::to_string(inf); 138 | REQUIRE(inf_str.size() >= 3); 139 | REQUIRE(inf_str[0] == 'i'); 140 | REQUIRE(inf_str[1] == 'n'); 141 | REQUIRE(inf_str[2] == 'f'); 142 | 143 | inf_str = ${COMP_NAMESPACE}::to_string(-inf); 144 | REQUIRE(inf_str.size() >= 4); 145 | REQUIRE(inf_str[0] == '-'); 146 | REQUIRE(inf_str[1] == 'i'); 147 | REQUIRE(inf_str[2] == 'n'); 148 | REQUIRE(inf_str[3] == 'f'); 149 | 150 | auto nan_str = ${COMP_NAMESPACE}::to_string(nan); 151 | REQUIRE(nan_str.size() >= 3); 152 | REQUIRE(nan_str[0] == 'n'); 153 | REQUIRE(nan_str[1] == 'a'); 154 | REQUIRE(nan_str[2] == 'n'); 155 | 156 | nan_str = ${COMP_NAMESPACE}::to_string(-nan); 157 | REQUIRE(nan_str.size() >= 4); 158 | REQUIRE(nan_str[0] == '-'); 159 | REQUIRE(nan_str[1] == 'n'); 160 | REQUIRE(nan_str[2] == 'a'); 161 | REQUIRE(nan_str[3] == 'n'); 162 | 163 | REQUIRE(${COMP_NAMESPACE}::to_string(min) != \"\"); 164 | REQUIRE(${COMP_NAMESPACE}::to_string(max) != \"\"); 165 | } 166 | " 167 | " 168 | test_integer(); 169 | test_integer(); 170 | test_integer(); 171 | 172 | test_unsigned_integer(); 173 | test_unsigned_integer(); 174 | test_unsigned_integer(); 175 | 176 | test_float(); 177 | test_float(); 178 | test_float(); 179 | ") 180 | -------------------------------------------------------------------------------- /cpp14_lang.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp14_lang/deprecated) 6 | comp_fetch_include(cpp14_lang/general_constexpr) 7 | comp_fetch_include(cpp14_lang/return_type_deduction) 8 | comp_fetch_include(cpp14_lang/sized_deallocation) 9 | comp_fetch_include(cpp14_lang/variable_template) 10 | -------------------------------------------------------------------------------- /cpp14_lang/deprecated.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(deprecated "[[deprecated]] int f(); int main() {}" COMP_CPP14_FLAG) 11 | comp_workaround(deprecated 12 | "#ifndef ${COMP_PREFIX}DEPRECATED 13 | #if ${COMP_PREFIX}HAS_DEPRECATED 14 | #define ${COMP_PREFIX}DEPRECATED [[deprecated]] 15 | #define ${COMP_PREFIX}DEPRECATED_MSG(Msg) [[deprecated(Msg)]] 16 | #elif defined(__GNUC__) 17 | #define ${COMP_PREFIX}DEPRECATED __attribute__((deprecated)) 18 | #define ${COMP_PREFIX}DEPRECATED_MSG(Msg) __attribute__((deprecated(Msg))) 19 | #elif defined(_MSC_VER) 20 | #define ${COMP_PREFIX}DEPRECATED __declspec(deprecated) 21 | #define ${COMP_PREFIX}DEPRECATED_MSG(Msg) __declspec(deprecated(Msg)) 22 | #else 23 | #define ${COMP_PREFIX}DEPRECATED 24 | #define ${COMP_PREFIX}DEPRECATED_MSG(Msg) 25 | #endif 26 | #endif" COMP_CPP98_FLAG) -------------------------------------------------------------------------------- /cpp14_lang/general_constexpr.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(general_constexpr 11 | "constexpr int foo() {int i = 0; return i;} int main() {}" COMP_CPP14_FLAG 12 | cpp11_lang/constexpr) 13 | 14 | if(COMP_API_VERSION VERSION_GREATER 1.0) 15 | comp_sd6_macro(general_constexpr __cpp_constexpr 201304) 16 | endif() 17 | -------------------------------------------------------------------------------- /cpp14_lang/return_type_deduction.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(return_type_deduction 11 | "auto foo() 12 | { 13 | return 2; 14 | } 15 | 16 | int main() {}" COMP_CPP14_FLAG) 17 | 18 | comp_workaround(return_type_deduction 19 | "#ifndef ${COMP_PREFIX}AUTO_RETURN 20 | #define ${COMP_PREFIX}AUTO_RETURN(...) decltype(__VA_ARGS__) {return (__VA_ARGS__);} 21 | #endif" COMP_CPP11_FLAG) 22 | 23 | if(COMP_API_VERSION VERSION_GREATER 1.0) 24 | comp_sd6_macro(return_type_deduction __cpp_return_type_deduction 201304) 25 | endif() 26 | -------------------------------------------------------------------------------- /cpp14_lang/sized_deallocation.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(sized_deallocation 11 | "int main() 12 | { 13 | void *ptr = 0; 14 | ::operator delete(ptr, 0); 15 | }" COMP_CPP14_FLAG) 16 | 17 | if(COMP_API_VERSION VERSION_GREATER 1.0) 18 | comp_sd6_macro(sized_deallocation __cpp_sized_deallocation 201309) 19 | endif() 20 | -------------------------------------------------------------------------------- /cpp14_lang/variable_template.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(variable_template "template T def = T(); int main() {}" COMP_CPP14_FLAG) 11 | 12 | if(COMP_API_VERSION VERSION_GREATER 1.0) 13 | comp_sd6_macro(variable_template __cpp_variable_templates 201304) 14 | endif() 15 | -------------------------------------------------------------------------------- /cpp14_lib.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp14_lib/exchange) 6 | comp_fetch_include(cpp14_lib/generic_operator_functors) 7 | comp_fetch_include(cpp14_lib/integer_sequence) 8 | comp_fetch_include(cpp14_lib/make_unique) 9 | comp_fetch_include(cpp14_lib/quoted) 10 | comp_fetch_include(cpp14_lib/shared_lock) 11 | comp_fetch_include(cpp14_lib/two_range_algorithms) 12 | -------------------------------------------------------------------------------- /cpp14_lib/exchange.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(exchange 11 | "#include 12 | 13 | int main() 14 | { 15 | int val = 4; 16 | int old_val = std::exchange(val, 5); 17 | }" COMP_CPP14_FLAG) 18 | comp_workaround(exchange 19 | "namespace ${COMP_NAMESPACE} 20 | { 21 | #if ${COMP_PREFIX}HAS_EXCHANGE 22 | using std::exchange; 23 | #else 24 | // see N3668 25 | template 26 | T exchange(T &obj, U &&new_val) 27 | { 28 | T old_val = std::move(obj); 29 | obj = std::forward(new_val); 30 | return old_val; 31 | } 32 | #endif 33 | }" COMP_CPP11_FLAG) 34 | 35 | if(COMP_API_VERSION VERSION_GREATER 1.0) 36 | comp_sd6_macro(exchange __cpp_lib_exchange_function 201304) 37 | endif() -------------------------------------------------------------------------------- /cpp14_lib/generic_operator_functors.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(generic_operator_functors 11 | "#include 12 | int main() 13 | { 14 | bool val = std::greater<>{}(4, 5); 15 | }" COMP_CPP14_FLAG) 16 | comp_workaround(generic_operator_functors 17 | "#include 18 | 19 | namespace ${COMP_NAMESPACE} 20 | { 21 | #define ${COMP_PREFIX}DETAIL_AUTO_RETURN(x) decltype(x) {return x;} 22 | 23 | // only the generic version 24 | 25 | struct plus 26 | { 27 | typedef void is_transparent; 28 | 29 | template 30 | auto operator()(T&& t, U &&u) const 31 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) + std::forward(u)) 32 | }; 33 | 34 | struct minus 35 | { 36 | typedef void is_transparent; 37 | 38 | template 39 | auto operator()(T&& t, U &&u) const 40 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) - std::forward(u)) 41 | }; 42 | 43 | struct multiplies 44 | { 45 | typedef void is_transparent; 46 | 47 | template 48 | auto operator()(T&& t, U &&u) const 49 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) * std::forward(u)) 50 | }; 51 | 52 | struct divides 53 | { 54 | typedef void is_transparent; 55 | 56 | template 57 | auto operator()(T&& t, U &&u) const 58 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) / std::forward(u)) 59 | }; 60 | 61 | struct modulus 62 | { 63 | typedef void is_transparent; 64 | 65 | template 66 | auto operator()(T&& t, U &&u) const 67 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) % std::forward(u)) 68 | }; 69 | 70 | struct negate 71 | { 72 | typedef void is_transparent; 73 | 74 | template 75 | auto operator()(T&& t) const 76 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(-std::forward(t)) 77 | }; 78 | 79 | struct equal_to 80 | { 81 | typedef void is_transparent; 82 | 83 | template 84 | auto operator()(T&& t, U &&u) const 85 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) == std::forward(u)) 86 | }; 87 | 88 | struct not_equal_to 89 | { 90 | typedef void is_transparent; 91 | 92 | template 93 | auto operator()(T&& t, U &&u) const 94 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) != std::forward(u)) 95 | }; 96 | 97 | struct greater 98 | { 99 | typedef void is_transparent; 100 | 101 | template 102 | auto operator()(T&& t, U &&u) const 103 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) > std::forward(u)) 104 | }; 105 | 106 | struct greater_equal 107 | { 108 | typedef void is_transparent; 109 | 110 | template 111 | auto operator()(T&& t, U &&u) const 112 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) >= std::forward(u)) 113 | }; 114 | 115 | struct less 116 | { 117 | typedef void is_transparent; 118 | 119 | template 120 | auto operator()(T&& t, U &&u) const 121 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) < std::forward(u)) 122 | }; 123 | 124 | struct less_equal 125 | { 126 | typedef void is_transparent; 127 | 128 | template 129 | auto operator()(T&& t, U &&u) const 130 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) <= std::forward(u)) 131 | }; 132 | 133 | struct logical_and 134 | { 135 | typedef void is_transparent; 136 | 137 | template 138 | auto operator()(T&& t, U &&u) const 139 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) && std::forward(u)) 140 | }; 141 | 142 | struct logical_or 143 | { 144 | typedef void is_transparent; 145 | 146 | template 147 | auto operator()(T&& t, U &&u) const 148 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) || std::forward(u)) 149 | }; 150 | 151 | struct logical_not 152 | { 153 | typedef void is_transparent; 154 | 155 | template 156 | auto operator()(T&& t) const 157 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(!std::forward(t)) 158 | }; 159 | 160 | struct bit_and 161 | { 162 | typedef void is_transparent; 163 | 164 | template 165 | auto operator()(T&& t, U &&u) const 166 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) & std::forward(u)) 167 | }; 168 | 169 | struct bit_or 170 | { 171 | typedef void is_transparent; 172 | 173 | template 174 | auto operator()(T&& t, U &&u) const 175 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) | std::forward(u)) 176 | }; 177 | 178 | struct bit_xor 179 | { 180 | typedef void is_transparent; 181 | 182 | template 183 | auto operator()(T&& t, U &&u) const 184 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(std::forward(t) ^ std::forward(u)) 185 | }; 186 | 187 | struct bit_not 188 | { 189 | typedef void is_transparent; 190 | 191 | template 192 | auto operator()(T&& t) const 193 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(~std::forward(t)) 194 | }; 195 | 196 | #undef ${COMP_PREFIX}DETAIL_AUTO_RETURN 197 | }" COMP_CPP11_FLAG) 198 | 199 | if(COMP_API_VERSION VERSION_GREATER 1.0) 200 | comp_sd6_macro(generic_operator_functors __cpp_lib_transparent_operators 201210) 201 | endif() 202 | -------------------------------------------------------------------------------- /cpp14_lib/integer_sequence.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(integer_sequence 11 | "#include 12 | 13 | int main() 14 | { 15 | std::make_index_sequence<4> f; 16 | }" COMP_CPP14_FLAG) 17 | comp_workaround(integer_sequence 18 | " 19 | #include 20 | #include 21 | 22 | namespace ${COMP_NAMESPACE} 23 | { 24 | #if ${COMP_PREFIX}HAS_INTEGER_SEQUENCE 25 | using std::integer_sequence; 26 | using std::index_sequence; 27 | using std::make_integer_sequence; 28 | using std::make_index_sequence; 29 | using std::index_sequence_for; 30 | #else 31 | template 32 | class integer_sequence 33 | { 34 | public: 35 | using value_type = Integer; 36 | 37 | static ${COMP_PREFIX}CONSTEXPR std::size_t size() 38 | { 39 | return sizeof...(Ints); 40 | } 41 | }; 42 | 43 | template 44 | using index_sequence = integer_sequence; 45 | 46 | namespace detail 47 | { 48 | template 49 | struct make_integer_sequence 50 | : make_integer_sequence, 51 | N::value - 1, Tail...> 52 | {}; 53 | 54 | template 55 | struct make_integer_sequence, Tail...> 56 | { 57 | using type = integer_sequence; 58 | }; 59 | } 60 | 61 | template 62 | using make_integer_sequence = typename detail::make_integer_sequence>::type; 64 | 65 | template 66 | using make_index_sequence = make_integer_sequence; 67 | 68 | template 69 | using index_sequence_for = make_index_sequence; 70 | #endif 71 | }" COMP_CPP11_FLAG cpp11_lang/constexpr) 72 | 73 | if(COMP_API_VERSION VERSION_GREATER 1.0) 74 | comp_sd6_macro(integer_sequence __cpp_lib_integer_sequence 201304) 75 | endif() -------------------------------------------------------------------------------- /cpp14_lib/make_unique.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(make_unique "#include 11 | int main() {std::unique_ptr ptr = std::make_unique(4);}" 12 | COMP_CPP14_FLAG) 13 | comp_workaround(make_unique 14 | "#include 15 | #include 16 | 17 | namespace ${COMP_NAMESPACE} 18 | { 19 | template 20 | auto make_unique(Args&&... args) 21 | -> typename std::enable_if::value, 22 | std::unique_ptr>::type 23 | { 24 | #if ${COMP_PREFIX}HAS_MAKE_UNIQUE 25 | return std::make_unique(std::forward(args)...); 26 | #else 27 | return std::unique_ptr(new T(std::forward(args)...)); 28 | #endif 29 | } 30 | 31 | template 32 | auto make_unique(std::size_t size) 33 | -> typename std::enable_if::value, 34 | std::unique_ptr>::type 35 | { 36 | #if ${COMP_PREFIX}HAS_MAKE_UNIQUE 37 | return std::make_unique(size); 38 | #else 39 | return std::unique_ptr(new typename std::remove_extent::type[size]()); 40 | #endif 41 | } 42 | }" COMP_CPP11_FLAG) 43 | 44 | if(COMP_API_VERSION VERSION_GREATER 1.0) 45 | comp_sd6_macro(make_unique __cpp_lib_make_unique 201304) 46 | endif() 47 | -------------------------------------------------------------------------------- /cpp14_lib/quoted.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(quoted "#include 11 | #include 12 | 13 | int main() 14 | { 15 | std::stringstream ss; 16 | std::string foo = \"a b\"; 17 | ss << std::quoted(foo); 18 | ss >> std::quoted(foo); 19 | }" COMP_CPP14_FLAG) 20 | if(COMP_API_VERSION VERSION_GREATER 1.0) 21 | comp_sd6_macro(quoted __cpp_lib_quoted_string_io 201304) 22 | endif() 23 | -------------------------------------------------------------------------------- /cpp14_lib/shared_lock.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(shared_lock "#include 11 | int main() 12 | { 13 | std::shared_timed_mutex m; 14 | std::shared_lock lock(m); 15 | }" COMP_CPP14_FLAG) 16 | 17 | if(COMP_API_VERSION VERSION_GREATER 1.0) 18 | comp_sd6_macro(shared_lock __cpp_lib_shared_timed_mutex 201402) 19 | endif() 20 | -------------------------------------------------------------------------------- /cpp14_lib/two_range_algorithms.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(two_range_algorithms 11 | "#include 12 | 13 | int main() 14 | { 15 | int a[] = {1, 2, 3}; 16 | int b[] = {3, 2, 1}; 17 | bool eq = std::equal(a, a + 3, b, b + 3); 18 | std::mismatch(a, a + 3, b, b + 3); 19 | bool per = std::is_permutation(a, a + 3, b, b + 3); 20 | }" COMP_CPP14_FLAG) 21 | comp_workaround(two_range_algorithms 22 | "#include 23 | #include 24 | 25 | namespace ${COMP_NAMESPACE} 26 | { 27 | template 28 | std::pair mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2) 29 | { 30 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 31 | return std::mismatch(first1, last1, first2, last2); 32 | #else 33 | // taken from cppreference.com 34 | while (first1 != last1 && first2 != last2 && *first1 == *first2) 35 | ++first1, ++first2; 36 | return std::make_pair(first1, first2); 37 | #endif 38 | } 39 | 40 | template 41 | std::pair mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred) 42 | { 43 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 44 | return std::mismatch(first1, last1, first2, last2, pred); 45 | #else 46 | // taken from cppreference.com 47 | while (first1 != last1 && first2 != last2 && pred(*first1, *first2)) 48 | ++first1, ++first2; 49 | return std::make_pair(first1, first2); 50 | #endif 51 | } 52 | 53 | #if !${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 54 | namespace detail 55 | { 56 | template 57 | bool equal(std::input_iterator_tag, Iter1 first1, Iter1 last1, 58 | std::input_iterator_tag, Iter2 first2, Iter2 last2) 59 | { 60 | while (first1 != last1 && first2 != last2) 61 | { 62 | if (*first1 != *last2) 63 | return false; 64 | } 65 | return first1 == last1 && first2 == last2; 66 | } 67 | 68 | template 69 | bool equal(std::input_iterator_tag, Iter1 first1, Iter1 last1, 70 | std::input_iterator_tag, Iter2 first2, Iter2 last2, Pred p) 71 | { 72 | while (first1 != last1 && first2 != last2) 73 | { 74 | if (!p(*first1, *last2)) 75 | return false; 76 | } 77 | return first1 == last1 && first2 == last2; 78 | } 79 | 80 | template 81 | bool equal(std::random_access_iterator_tag, Iter1 first1, Iter1 last1, 82 | std::random_access_iterator_tag, Iter2 first2, Iter2 last2) 83 | { 84 | if (last1 - first1 != last2 - first2) 85 | return false; 86 | return std::equal(first1, last1, first2); 87 | } 88 | 89 | template 90 | bool equal(std::random_access_iterator_tag, Iter1 first1, Iter1 last1, 91 | std::random_access_iterator_tag, Iter2 first2, Iter2 last2, 92 | Pred p) 93 | { 94 | if (last1 - first1 != last2 - first2) 95 | return false; 96 | return std::equal(first1, last1, first2, p); 97 | } 98 | } 99 | #endif 100 | 101 | template 102 | bool equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2) 103 | { 104 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 105 | return std::equal(first1, last1, first2, last2); 106 | #else 107 | return detail::equal(typename std::iterator_traits::iterator_category{}, first1, last1, 108 | typename std::iterator_traits::iterator_category{}, first2, last2); 109 | #endif 110 | } 111 | 112 | template 113 | bool equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred) 114 | { 115 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 116 | return std::equal(first1, last1, first2, last2, pred); 117 | #else 118 | return detail::equal(typename std::iterator_traits::iterator_category{}, first1, last1, 119 | typename std::iterator_traits::iterator_category{}, first2, last2, 120 | pred); 121 | #endif 122 | } 123 | 124 | template 125 | bool is_permutation(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2) 126 | { 127 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 128 | return std::is_permutation(first1, last1, first2, last2); 129 | #else 130 | if (std::distance(first1, last1) != std::distance(first2, last2)) 131 | return false; 132 | return std::is_permutation(first1, last1, first2); 133 | #endif 134 | } 135 | 136 | template 137 | bool is_permutation(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred) 138 | { 139 | #if ${COMP_PREFIX}HAS_TWO_RANGE_ALGORITHMS 140 | return std::is_permutation(first1, last1, first2, last2, pred); 141 | #else 142 | if (std::distance(first1, last1) != std::distance(first2, last2)) 143 | return false; 144 | return std::is_permutation(first1, last1, first2, pred); 145 | #endif 146 | } 147 | }" COMP_CPP98_FLAG) 148 | 149 | if(COMP_API_VERSION VERSION_GREATER 1.0) 150 | comp_sd6_macro(two_range_algorithms __cpp_lib_robust_nonmodifying_seq_ops 201304) 151 | endif() 152 | 153 | comp_unit_test(two_range_algorithms 154 | "" 155 | " 156 | using namespace ${COMP_NAMESPACE}; 157 | 158 | int a[] = {1, 2, 3}; 159 | int b[] = {3, 1, 2}; 160 | int c[] = {1, 2, 3, 4}; 161 | 162 | SECTION(\"equal\") 163 | { 164 | REQUIRE(equal(a, a + 0, b, b + 0)); 165 | REQUIRE(equal(a, a + 3, a, a + 3)); 166 | REQUIRE(!equal(a, a + 3, b, b + 3)); 167 | REQUIRE(!equal(a, a + 3, c, c + 4)); 168 | } 169 | SECTION(\"equal predicate\") 170 | { 171 | REQUIRE(${COMP_NAMESPACE}::equal(a, a + 0, b, b + 0, std::not_equal_to{})); 172 | REQUIRE((!${COMP_NAMESPACE}::equal(a, a + 3, a, a + 3, std::not_equal_to{}))); 173 | REQUIRE(${COMP_NAMESPACE}::equal(a, a + 3, b, b + 3, std::not_equal_to{})); 174 | REQUIRE((!${COMP_NAMESPACE}::equal(a, a + 3, c, c + 4, std::not_equal_to{}))); 175 | } 176 | 177 | SECTION(\"is_permutation\") 178 | { 179 | REQUIRE(is_permutation(a, a + 0, b, b + 0)); 180 | REQUIRE(is_permutation(a, a + 3, a, a + 3)); 181 | REQUIRE(is_permutation(a, a + 3, b, b + 3)); 182 | REQUIRE(!is_permutation(a, a + 3, c, c + 4)); 183 | } 184 | 185 | SECTION(\"mismatch\") 186 | { 187 | std::pair mm; 188 | 189 | mm = mismatch(a, a + 0, b, b + 0); 190 | REQUIRE(mm.first == a); 191 | REQUIRE(mm.second == b); 192 | 193 | mm = mismatch(a, a + 3, a, a + 3); 194 | REQUIRE(mm.first == a + 3); 195 | REQUIRE(mm.second == a + 3); 196 | 197 | mm = mismatch(a, a + 3, b, b + 3); 198 | REQUIRE(mm.first == a); 199 | REQUIRE(mm.second == b); 200 | 201 | mm = mismatch(a, a + 3, c, c + 4); 202 | REQUIRE(mm.first == a + 3); 203 | REQUIRE(mm.second == c + 3); 204 | } 205 | SECTION(\"mismatch predicate\") 206 | { 207 | std::pair mm; 208 | 209 | mm = ${COMP_NAMESPACE}::mismatch(a, a + 0, b, b + 0, std::not_equal_to{}); 210 | REQUIRE(mm.first == a); 211 | REQUIRE(mm.second == b); 212 | 213 | mm = ${COMP_NAMESPACE}::mismatch(a, a + 3, a, a + 3, std::not_equal_to{}); 214 | REQUIRE(mm.first == a); 215 | REQUIRE(mm.second == a); 216 | 217 | mm = ${COMP_NAMESPACE}::mismatch(a, a + 3, b, b + 3, std::not_equal_to{}); 218 | REQUIRE(mm.first == a + 3); 219 | REQUIRE(mm.second == b + 3); 220 | 221 | mm = ${COMP_NAMESPACE}::mismatch(a, a + 3, c, c + 4, std::not_equal_to{}); 222 | REQUIRE(mm.first == a); 223 | REQUIRE(mm.second == c); 224 | }") 225 | -------------------------------------------------------------------------------- /cpp17_lang.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp17_lang/fold_expressions) 6 | comp_fetch_include(cpp17_lang/terse_static_assert) 7 | comp_fetch_include(cpp17_lang/utf8_char_literal) 8 | -------------------------------------------------------------------------------- /cpp17_lang/fold_expressions.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(fold_expressions 11 | "template 12 | bool all(Args... args) {return (args && ...);} 13 | int main() 14 | { 15 | bool b = all(true, true, false, true); 16 | }" 17 | COMP_CPP17_FLAG) 18 | 19 | if(COMP_API_VERSION VERSION_GREATER 1.0) 20 | comp_sd6_macro(fold_expressions __cpp_fold_expressions 201411) 21 | endif() 22 | -------------------------------------------------------------------------------- /cpp17_lang/terse_static_assert.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(terse_static_assert 11 | "int main() {static_assert(true);}" 12 | COMP_CPP17_FLAG) 13 | comp_workaround(terse_static_assert 14 | "#ifndef ${COMP_PREFIX}TERSE_STATIC_ASSERT 15 | #if ${COMP_PREFIX}HAS_TERSE_STATIC_ASSERT 16 | #define ${COMP_PREFIX}TERSE_STATIC_ASSERT(Expr) static_assert(Expr) 17 | #else 18 | #define ${COMP_PREFIX}TERSE_STATIC_ASSERT(Expr) static_assert(Expr, #Expr) 19 | #endif 20 | #endif" COMP_CPP11_FLAG) 21 | 22 | if(COMP_API_VERSION VERSION_GREATER 1.0) 23 | comp_sd6_macro(terse_static_assert __cpp_static_assert 201411) 24 | endif() 25 | -------------------------------------------------------------------------------- /cpp17_lang/utf8_char_literal.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(utf8_char_literal "int main() {char c = u8'A';}" COMP_CPP17_FLAG) 11 | comp_workaround(utf8_char_literal 12 | "#ifndef ${COMP_PREFIX}UTF8_CHAR_LITERAL 13 | #define ${COMP_PREFIX}UTF8_CHAR_LITERAL_IMPL(Str) u8##Str[0] 14 | #define ${COMP_PREFIX}UTF8_CHAR_LITERAL(Str) ${COMP_PREFIX}UTF8_CHAR_LITERAL_IMPL(Str) 15 | #endif" COMP_CPP11_FLAG) 16 | 17 | if(COMP_API_VERSION VERSION_GREATER 1.0) 18 | comp_sd6_macro(utf8_char_literal __cpp_unicode_characters 201411) 19 | endif() 20 | -------------------------------------------------------------------------------- /cpp17_lib.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(cpp17_lib/bool_constant) 6 | comp_fetch_include(cpp17_lib/container_access) 7 | comp_fetch_include(cpp17_lib/invoke) 8 | comp_fetch_include(cpp17_lib/map_insertion) 9 | comp_fetch_include(cpp17_lib/shared_mutex) 10 | comp_fetch_include(cpp17_lib/uncaught_exceptions) 11 | comp_fetch_include(cpp17_lib/void_t) 12 | -------------------------------------------------------------------------------- /cpp17_lib/bool_constant.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(bool_constant 11 | "#include 12 | int main() 13 | { 14 | std::bool_constant b; 15 | }" 16 | COMP_CPP17_FLAG) 17 | comp_workaround(bool_constant 18 | "#include 19 | 20 | namespace ${COMP_NAMESPACE} 21 | { 22 | template 23 | using bool_constant = std::integral_constant; 24 | 25 | typedef bool_constant true_type; 26 | typedef bool_constant false_type; 27 | }" COMP_CPP11_FLAG) 28 | -------------------------------------------------------------------------------- /cpp17_lib/container_access.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(container_access 11 | "#include 12 | #include 13 | int main() 14 | { 15 | int array[3]; 16 | std::size(array); 17 | std::data(array); 18 | std::empty(array); 19 | std::vector vec; 20 | std::size(vec); 21 | std::data(vec); 22 | std::empty(vec); 23 | }" COMP_CPP17_FLAG) 24 | comp_workaround(container_access 25 | "#include 26 | #include 27 | 28 | namespace ${COMP_NAMESPACE} 29 | { 30 | #if ${COMP_PREFIX}HAS_CONTAINER_ACCESS 31 | using std::size; 32 | using std::empty; 33 | using std::data; 34 | #else 35 | // see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4280.pdf 36 | template 37 | ${COMP_PREFIX}CONSTEXPR_FNC auto size(const C &c) -> decltype(c.size()) 38 | { 39 | return c.size(); 40 | } 41 | 42 | template 43 | ${COMP_PREFIX}CONSTEXPR_FNC std::size_t size(const T (&) [N]) ${COMP_PREFIX}NOEXCEPT 44 | { 45 | return N; 46 | } 47 | 48 | template 49 | ${COMP_PREFIX}CONSTEXPR_FNC auto empty(const C &c) -> decltype(c.empty()) 50 | { 51 | return c.empty(); 52 | } 53 | 54 | template 55 | ${COMP_PREFIX}CONSTEXPR_FNC bool empty(const T (&) [N]) ${COMP_PREFIX}NOEXCEPT 56 | { 57 | return false; 58 | } 59 | 60 | template 61 | ${COMP_PREFIX}CONSTEXPR_FNC bool empty(std::initializer_list list) ${COMP_PREFIX}NOEXCEPT 62 | { 63 | return list.size() == 0u; 64 | } 65 | 66 | template 67 | ${COMP_PREFIX}CONSTEXPR_FNC auto data(C &c) -> decltype(c.data()) 68 | { 69 | return c.data(); 70 | } 71 | 72 | template 73 | ${COMP_PREFIX}CONSTEXPR_FNC auto data(const C &c) -> decltype(c.data()) 74 | { 75 | return c.data(); 76 | } 77 | 78 | template 79 | ${COMP_PREFIX}CONSTEXPR_FNC T* data(const T (&array) [N]) ${COMP_PREFIX}NOEXCEPT 80 | { 81 | return array; 82 | } 83 | 84 | template 85 | ${COMP_PREFIX}CONSTEXPR_FNC const T* data(std::initializer_list list) ${COMP_PREFIX}NOEXCEPT 86 | { 87 | return list.begin(); 88 | } 89 | #endif 90 | }" COMP_CPP11_FLAG cpp11_lang/constexpr cpp11_lang/noexcept) 91 | 92 | if(COMP_API_VERSION VERSION_GREATER 1.0) 93 | comp_sd6_macro(container_access __cpp_lib_nonmember_container_access 201411) 94 | endif() -------------------------------------------------------------------------------- /cpp17_lib/invoke.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(invoke "#include 11 | void foo() {} 12 | int main() 13 | { 14 | std::invoke(foo); 15 | }" COMP_CPP17_FLAG) 16 | comp_workaround(invoke 17 | "#include 18 | #include 19 | 20 | // see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4169.html 21 | namespace ${COMP_NAMESPACE} 22 | { 23 | #if ${COMP_PREFIX}HAS_INVOKE 24 | using std::invoke; 25 | #else 26 | template 27 | typename std::enable_if< 28 | std::is_member_pointer::type>::value, 29 | typename std::result_of::type 30 | >::type invoke(Functor&& f, Args&&... args) 31 | { 32 | return std::mem_fn(f)(std::forward(args)...); 33 | } 34 | 35 | template 36 | typename std::enable_if< 37 | !std::is_member_pointer::type>::value, 38 | typename std::result_of::type 39 | >::type invoke(Functor&& f, Args&&... args) 40 | { 41 | return std::forward(f)(std::forward(args)...); 42 | } 43 | #endif 44 | }" COMP_CPP11_FLAG) 45 | 46 | if(COMP_API_VERSION VERSION_GREATER 1.0) 47 | comp_sd6_macro(invoke __cpp_lib_invoke 201411) 48 | endif() 49 | -------------------------------------------------------------------------------- /cpp17_lib/map_insertion.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(map_insertion 11 | "#include 12 | int main() 13 | { 14 | std::map m; 15 | m.try_emplace(5, 5); 16 | m.insert_or_assign(10, 5); 17 | }" COMP_CPP17_FLAG) 18 | comp_workaround(map_insertion 19 | "#include 20 | 21 | namespace ${COMP_NAMESPACE} 22 | { 23 | #if ${COMP_PREFIX}HAS_MAP_INSERTION 24 | template 25 | std::pair 26 | try_emplace(Map &m, Key &&key, Args&&... args) 27 | { 28 | return m.try_emplace(std::forward(key), std::forward(args)...); 29 | } 30 | 31 | template 32 | typename Map::iterator 33 | try_emplace(Map &m, typename Map::const_iterator hint, Key &&key, Args&&... args) 34 | { 35 | return m.try_emplace(hint, std::forward(key), std::forward(args)...); 36 | } 37 | 38 | template 39 | std::pair 40 | insert_or_assign(Map &m, Key &&key, M &&obj) 41 | { 42 | return m.insert_or_assign(std::forward(key), std::forward(obj)); 43 | } 44 | 45 | template 46 | typename Map::iterator 47 | insert_or_assign(Map &m, typename Map::const_iterator hint, Key &&key, M &&obj) 48 | { 49 | return m.insert_or_assign(hint, std::forward(key), std::forward(obj)); 50 | } 51 | #else 52 | template 53 | std::pair 54 | try_emplace(Map &m, Key &&key, Args&&... args) 55 | { 56 | typename Map::iterator iter = m.find(key); 57 | if (iter != m.end()) 58 | return {iter, false}; 59 | return m.insert(typename Map::value_type(std::forward(key), std::forward(args)...)); 60 | } 61 | 62 | template 63 | typename Map::iterator 64 | try_emplace(Map &m, typename Map::const_iterator hint, Key &&key, Args&&... args) 65 | { 66 | typename Map::iterator iter = m.find(key); 67 | if (iter != m.end()) 68 | return iter; 69 | return m.insert(hint, typename Map::value_type(std::forward(key), std::forward(args)...)).first; 70 | } 71 | 72 | template 73 | std::pair 74 | insert_or_assign(Map &m, Key &&key, M &&obj) 75 | { 76 | typename Map::iterator iter = m.find(key); 77 | if (iter != m.end()) 78 | { 79 | iter->second = std::forward(obj); 80 | return {iter, false}; 81 | } 82 | return m.insert(typename Map::value_type(std::forward(key), std::forward(obj))); 83 | } 84 | 85 | template 86 | typename Map::iterator 87 | insert_or_assign(Map &m, typename Map::const_iterator hint, Key &&key, M &&obj) 88 | { 89 | typename Map::iterator iter = m.find(key); 90 | if (iter != m.end()) 91 | { 92 | iter->second = std::forward(obj); 93 | return iter; 94 | } 95 | m.insert(hint, typename Map::value_type(std::forward(key), std::forward(obj))).first; 96 | } 97 | #endif 98 | }" COMP_CPP11_FLAG) 99 | 100 | if(COMP_API_VERSION VERSION_GREATER 1.0) 101 | comp_sd6_macro(map_insertion __cpp_lib_map_insertion 201411) 102 | comp_sd6_macro(map_insertion __cpp_lib_unordered_map_insertion 201411) 103 | comp_sd6_macro(map_insertion __cpp_lib_map_try_emplace 201411) 104 | comp_sd6_macro(map_insertion __cpp_lib_unordered_map_try_emplace 201411) 105 | endif() 106 | 107 | comp_unit_test(map_insertion 108 | " 109 | #include 110 | " 111 | " 112 | std::map map; 113 | auto res = ${COMP_NAMESPACE}::try_emplace(map, 0, 0); 114 | REQUIRE(res.second == true); 115 | REQUIRE(res.first->second == 0); 116 | 117 | res = ${COMP_NAMESPACE}::try_emplace(map, 0, 1); 118 | REQUIRE(res.second == false); 119 | REQUIRE(res.first->second == 0); 120 | 121 | res = ${COMP_NAMESPACE}::insert_or_assign(map, 1, 1); 122 | REQUIRE(res.second == true); 123 | REQUIRE(res.first->second == 1); 124 | 125 | res = ${COMP_NAMESPACE}::insert_or_assign(map, 1, 2); 126 | REQUIRE(res.second == false); 127 | REQUIRE(res.first->second == 2); 128 | ") -------------------------------------------------------------------------------- /cpp17_lib/shared_mutex.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(shared_mutex "#include 11 | int main() 12 | { 13 | std::shared_mutex m; 14 | }" COMP_CPP17_FLAG) -------------------------------------------------------------------------------- /cpp17_lib/uncaught_exceptions.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(uncaught_exceptions 11 | "#include 12 | int main() 13 | { 14 | int count = std::uncaught_exceptions(); 15 | }" COMP_CPP17_FLAG) 16 | 17 | if(COMP_API_VERSION VERSION_GREATER 1.0) 18 | comp_sd6_macro(uncaught_exceptions __cpp_uncaught_exceptions 201411) 19 | endif() 20 | -------------------------------------------------------------------------------- /cpp17_lib/void_t.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(void_t "#include 11 | int main() 12 | { 13 | std::void_t *ptr; 14 | }" COMP_CPP17_FLAG) 15 | comp_workaround(void_t 16 | "// see proposal: http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2014/n3911.pdf 17 | namespace ${COMP_NAMESPACE} 18 | { 19 | namespace detail 20 | { 21 | template 22 | struct voider 23 | { 24 | typedef void type; 25 | }; 26 | } 27 | 28 | template 29 | using void_t = typename detail::voider::type; 30 | }" COMP_CPP1_FLAG) 31 | 32 | if(COMP_API_VERSION VERSION_GREATER 1.0) 33 | comp_sd6_macro(void_t __cpp_lib_void_t 201411) 34 | endif() 35 | -------------------------------------------------------------------------------- /env.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(env/exception_support) 6 | comp_fetch_include(env/hosted_implementation) 7 | comp_fetch_include(env/rtti_support) 8 | comp_fetch_include(env/threading_support) 9 | -------------------------------------------------------------------------------- /env/exception_support.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(exception_support 11 | "#include 12 | 13 | #if defined(__GNUC__) && !defined(__EXCEPTIONS) 14 | #error \"no exception support\" 15 | #elif defined(_MSC_VER) && !_HAS_EXCEPTIONS 16 | #error \"no exception support\" 17 | #endif 18 | 19 | struct my_exception {}; 20 | int main() 21 | { 22 | try 23 | { 24 | throw my_exception(); 25 | } 26 | catch (my_exception&) {} 27 | catch (...) {} 28 | }" COMP_CPP98_FLAG) 29 | comp_workaround(exception_support 30 | "#include 31 | 32 | #ifndef ${COMP_PREFIX}THROW 33 | #if ${COMP_PREFIX}HAS_EXCEPTION_SUPPORT 34 | #define ${COMP_PREFIX}THROW(Ex) throw (Ex) 35 | #else 36 | #define ${COMP_PREFIX}THROW(Ex) (Ex), std::abort() 37 | #endif 38 | #endif 39 | 40 | #ifndef ${COMP_PREFIX}RETHROW 41 | #if ${COMP_PREFIX}HAS_EXCEPTION_SUPPORT 42 | #define ${COMP_PREFIX}RETHROW throw 43 | #else 44 | #define ${COMP_PREFIX}RETHROW std::abort() 45 | #endif 46 | #endif 47 | 48 | #ifndef ${COMP_PREFIX}TRY 49 | #if ${COMP_PREFIX}HAS_EXCEPTION_SUPPORT 50 | #define ${COMP_PREFIX}TRY try 51 | #else 52 | #define ${COMP_PREFIX}TRY if (true) 53 | #endif 54 | #endif 55 | 56 | #ifndef ${COMP_PREFIX}CATCH_ALL 57 | #if ${COMP_PREFIX}HAS_EXCEPTION_SUPPORT 58 | #define ${COMP_PREFIX}CATCH_ALL catch(...) 59 | #else 60 | #define ${COMP_PREFIX}CATCH_ALL if (false) 61 | #endif 62 | #endif 63 | " COMP_CPP98_FLAG) 64 | 65 | -------------------------------------------------------------------------------- /env/hosted_implementation.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # uses macro __STDC_HOSTED__ 11 | comp_feature(hosted_implementation "#include 12 | #if !_MSC_VER && !__STDC_HOSTED__ 13 | #error \"no hosted\" 14 | #endif 15 | 16 | int main() {}" COMP_CPP98_FLAG) 17 | comp_workaround(hosted_implementation 18 | "// HAS_HOSTED_IMPLEMENTATION doesn't sond that nice... :D 19 | #define ${COMP_PREFIX}HOSTED_IMPLEMENTATION ${COMP_PREFIX}HAS_HOSTED_IMPLEMENTATION 20 | 21 | #include 22 | 23 | #if ${COMP_PREFIX}HOSTED_IMPLEMENTATION 24 | #include 25 | #endif 26 | 27 | namespace ${COMP_NAMESPACE} 28 | { 29 | #if ${COMP_PREFIX}HAS_RVALUE_REF 30 | // move - taken from http://stackoverflow.com/a/7518365 31 | template 32 | typename std::remove_reference::type&& move(T&& arg) ${COMP_PREFIX}NOEXCEPT 33 | { 34 | return static_cast::type&&>(arg); 35 | } 36 | 37 | // forward - taken from http://stackoverflow.com/a/27501759 38 | template 39 | T&& forward(typename std::remove_reference::type& t) ${COMP_PREFIX}NOEXCEPT 40 | { 41 | return static_cast(t); 42 | } 43 | 44 | template 45 | T&& forward(typename std::remove_reference::type&& t) ${COMP_PREFIX}NOEXCEPT 46 | { 47 | static_assert(!std::is_lvalue_reference::value, 48 | \"Can not forward an rvalue as an lvalue.\"); 49 | return static_cast(t); 50 | } 51 | #endif 52 | 53 | #if ${COMP_PREFIX}HOSTED_IMPLEMENTATION 54 | using std::swap; 55 | #else 56 | #if ${COMP_PREFIX}HAS_RVALUE_REF 57 | template 58 | void swap(T &a, T &b) ${COMP_PREFIX}NOEXCEPT_IF(std::is_nothrow_move_assignable::value 59 | && std::is_nothrow_move_constructible::value) 60 | { 61 | T tmp = move(a); 62 | a = move(b); 63 | b = move(tmp); 64 | } 65 | #else 66 | template 67 | void swap(T &a, T &b) 68 | { 69 | T tmp(a); 70 | a = b; 71 | b = tmp; 72 | } 73 | #endif 74 | #endif 75 | }" COMP_CPP98_FLAG cpp11_lang/noexcept cpp11_lang/rvalue_ref) 76 | -------------------------------------------------------------------------------- /env/rtti_support.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # small, dumb program using rtti 11 | comp_feature(rtti_support 12 | "#include 13 | struct a {virtual ~a() {}}; 14 | struct b : a {}; 15 | int main() 16 | { 17 | a *ptr = new b; 18 | b *b_ptr = dynamic_cast(ptr); 19 | bool res = typeid(*b_ptr) == typeid(*ptr); 20 | }" COMP_CPP98_FLAG) 21 | comp_workaround(rtti_support 22 | "namespace ${COMP_NAMESPACE} 23 | { 24 | template 25 | Derived polymorphic_downcast(Base *ptr) 26 | { 27 | #if ${COMP_PREFIX}HAS_RTTI_SUPPORT 28 | return dynamic_cast(ptr); 29 | #else 30 | return static_cast(ptr); 31 | #endif 32 | } 33 | 34 | template 35 | Derived polymorphic_downcast(Base &ref) 36 | { 37 | #if ${COMP_PREFIX}HAS_RTTI_SUPPORT 38 | return dynamic_cast(ref); 39 | #else 40 | return static_cast(ref); 41 | #endif 42 | } 43 | }" COMP_CPP98_FLAG) 44 | -------------------------------------------------------------------------------- /env/threading_support.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # small, dumb program that uses std::thread and std::mutex 11 | comp_feature(threading_support 12 | "#include 13 | #include 14 | 15 | void foo() {} 16 | 17 | int main() 18 | { 19 | std::thread thr(foo); 20 | std::mutex m; 21 | }" COMP_CPP11_FLAG) 22 | -------------------------------------------------------------------------------- /ext.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(ext/assume) 6 | comp_fetch_include(ext/bswap) 7 | comp_fetch_include(ext/clz) 8 | comp_fetch_include(ext/counter) 9 | comp_fetch_include(ext/ctz) 10 | comp_fetch_include(ext/expect) 11 | comp_fetch_include(ext/extension) 12 | comp_fetch_include(ext/fallthrough) 13 | comp_fetch_include(ext/has_include) 14 | comp_fetch_include(ext/int128) 15 | comp_fetch_include(ext/popcount) 16 | comp_fetch_include(ext/pretty_function) 17 | comp_fetch_include(ext/unreachable) 18 | comp_fetch_include(ext/unused) 19 | -------------------------------------------------------------------------------- /ext/assume.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(assume 11 | "#include 12 | 13 | int main() 14 | { 15 | int x = 3; 16 | __assume(x == 3); 17 | }" COMP_CPP98_FLAG) 18 | comp_workaround(assume 19 | "#ifndef ${COMP_PREFIX}ASSUME 20 | #if ${COMP_PREFIX}HAS_ASSUME 21 | #define ${COMP_PREFIX}ASSUME(expr) __assume(expr) 22 | #elif ${COMP_PREFIX}HAS_UNREACHABLE 23 | #define ${COMP_PREFIX}ASSUME(expr) \ 24 | do \ 25 | { \ 26 | if (!(expr)) \ 27 | ${COMP_PREFIX}UNREACHABLE; \ 28 | } while (false) 29 | #else 30 | #define ${COMP_PREFIX}ASSUME(expr) 31 | #endif 32 | #endif 33 | " COMP_CPP98_FLAG ext/unreachable) 34 | -------------------------------------------------------------------------------- /ext/bswap.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(bswap 11 | "#include 12 | 13 | template 14 | struct foo {}; 15 | 16 | int main() 17 | { 18 | int a = __builtin_bswap16(4); 19 | int b = __builtin_bswap32(4); 20 | int c = __builtin_bswap64(4); 21 | 22 | // require constant expression 23 | foo<__builtin_bswap16(4)> f; 24 | }" COMP_CPP11_FLAG) 25 | comp_workaround(bswap 26 | "#include 27 | 28 | // a function bswap() that swaps the bytes of an (unsigned) integer 29 | // it is overloaded for each std::uint(8,16,32,64)_t 30 | // e.g. OxAABB becomes 0xBBAA 31 | namespace ${COMP_NAMESPACE} 32 | { 33 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint8_t bswap(std::uint8_t x) 34 | { 35 | return x; 36 | } 37 | 38 | #if ${COMP_PREFIX}HAS_BSWAP 39 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint16_t bswap(std::uint16_t x) 40 | { 41 | return __builtin_bswap16(x); 42 | } 43 | 44 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint32_t bswap(std::uint32_t x) 45 | { 46 | return __builtin_bswap32(x); 47 | } 48 | 49 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t bswap(std::uint64_t x) 50 | { 51 | return __builtin_bswap64(x); 52 | } 53 | #else 54 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint16_t bswap(std::uint16_t x) 55 | { 56 | return (x & 0x00FFu) << 8 57 | | (x & 0xFF00u) >> 8; 58 | } 59 | 60 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint32_t bswap(std::uint32_t x) 61 | { 62 | return (x & 0x000000FFu) << 24 63 | | (x & 0x0000FF00u) << 8 64 | | (x & 0x00FF0000u) >> 8 65 | | (x & 0xFF000000u) >> 24; 66 | } 67 | 68 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t bswap(std::uint64_t x) 69 | { 70 | return (x & 0x00000000000000FFul) << 56 71 | | (x & 0x000000000000FF00ul) << 40 72 | | (x & 0x0000000000FF0000ul) << 24 73 | | (x & 0x00000000FF000000ul) << 8 74 | | (x & 0x000000FF00000000ul) >> 8 75 | | (x & 0x0000FF0000000000ul) >> 24 76 | | (x & 0x00FF000000000000ul) >> 40 77 | | (x & 0xFF00000000000000ul) >> 56; 78 | } 79 | #endif 80 | }" COMP_CPP11_FLAG cpp11_lang/constexpr) 81 | 82 | comp_unit_test(bswap 83 | "" 84 | " 85 | using ${COMP_NAMESPACE}::bswap; 86 | 87 | REQUIRE(bswap(std::uint8_t(0xAA)) == 0xAA); 88 | REQUIRE(bswap(std::uint16_t(0xAABB)) == 0xBBAA); 89 | REQUIRE(bswap(std::uint32_t(0xAABBCCDD)) == 0xDDCCBBAA); 90 | REQUIRE(bswap(std::uint64_t(0xAABBCCDDEEFF0011)) == 0x1100FFEEDDCCBBAA); 91 | ") 92 | -------------------------------------------------------------------------------- /ext/clz.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(clz 11 | "#include 12 | 13 | template 14 | struct foo {}; 15 | 16 | int main() 17 | { 18 | int a = __builtin_clz(4); 19 | int b = __builtin_clzl(4); 20 | int c = __builtin_clzll(4); 21 | 22 | // require constant expression 23 | foo<__builtin_clz(4)> f; 24 | }" COMP_CPP11_FLAG) 25 | comp_workaround(clz 26 | " 27 | #include 28 | #include 29 | #include 30 | 31 | // a function clz() that returns the number of leading zeros in an integer 32 | // overloaded for each of the fixed-sized integers, undefined for input value 0! 33 | // * if builtin available: uses the smallest integer version that is fitting 34 | // * otherwise: binary search implementation w/ lookup table for last 4 bits 35 | namespace ${COMP_NAMESPACE} 36 | { 37 | #if ${COMP_PREFIX}HAS_CLZ 38 | namespace detail 39 | { 40 | // prioritized tag dispatching to choose smallest integer that fits 41 | struct clzll_tag {}; 42 | struct clzl_tag : clzll_tag {}; 43 | struct clz_tag : clzl_tag {}; 44 | 45 | // also subtracts the number of addtional 0s that occur because the target type is smaller 46 | template ::type> 48 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(clz_tag, T x) 49 | { 50 | return __builtin_clz(x) - (sizeof(unsigned int) * CHAR_BIT - sizeof(T) * CHAR_BIT); 51 | } 52 | 53 | template ::type> 55 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(clzl_tag, T x) 56 | { 57 | return __builtin_clzl(x) - (sizeof(unsigned long) * CHAR_BIT - sizeof(T) * CHAR_BIT); 58 | } 59 | 60 | template ::type> 62 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(clzll_tag, T x) 63 | { 64 | return __builtin_clzll(x) - (sizeof(unsigned long long) * CHAR_BIT - sizeof(T) * CHAR_BIT); 65 | } 66 | } 67 | 68 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint8_t x) 69 | { 70 | return detail::clz(detail::clz_tag{}, x); 71 | } 72 | 73 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint16_t x) 74 | { 75 | return detail::clz(detail::clz_tag{}, x);; 76 | } 77 | 78 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint32_t x) 79 | { 80 | return detail::clz(detail::clz_tag{}, x); 81 | } 82 | 83 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint64_t x) 84 | { 85 | return detail::clz(detail::clz_tag{}, x); 86 | } 87 | #else 88 | namespace detail 89 | { 90 | ${COMP_PREFIX}CONSTEXPR std::uint8_t clz_lookup[16] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; 91 | 92 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz_base(std::uint8_t higher, std::uint8_t lower) 93 | { 94 | return higher ? clz_lookup[higher] : 4 + clz_lookup[lower]; 95 | } 96 | } 97 | 98 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint8_t x) 99 | { 100 | return detail::clz_base(x >> 4, x & 0x0Fu); 101 | } 102 | 103 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint16_t x) 104 | { 105 | return x >> 8 ? clz(std::uint8_t(x >> 8)) : 8 + clz(std::uint8_t(x & 0xFFu)); 106 | } 107 | 108 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint32_t x) 109 | { 110 | return x >> 16 ? clz(std::uint16_t(x >> 16)) : 16 + clz(std::uint16_t(x & 0xFFFFu)); 111 | } 112 | 113 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned clz(std::uint64_t x) 114 | { 115 | return x >> 32 ? clz(std::uint32_t(x >> 32)) : 32 + clz(std::uint32_t(x & 0xFFFFFFFFul)); 116 | } 117 | #endif 118 | }" COMP_CPP11_FLAG cpp11_lang/constexpr) 119 | comp_unit_test(clz 120 | "#include " 121 | " 122 | using ${COMP_NAMESPACE}::clz; 123 | // 8 bits 124 | REQUIRE(clz(std::uint8_t(1)) == 7); 125 | REQUIRE(clz(std::uint8_t(2)) == 6); 126 | REQUIRE(clz(std::uint8_t(127)) == 1); 127 | REQUIRE(clz(std::uint8_t(128)) == 0); 128 | REQUIRE(clz(std::uint8_t(200)) == 0); 129 | REQUIRE(clz(std::uint8_t(255)) == 0); 130 | 131 | // 16 bits 132 | REQUIRE(clz(std::uint16_t(1)) == 15); 133 | REQUIRE(clz(std::uint16_t(2)) == 14); 134 | REQUIRE(clz(std::uint16_t(128)) == 8); 135 | REQUIRE(clz(std::uint16_t(256)) == 7); 136 | REQUIRE(clz(std::uint16_t(0xFFFD)) == 0); 137 | REQUIRE(clz(std::uint16_t(0xFFFF)) == 0); 138 | 139 | // 32 bits 140 | REQUIRE(clz(std::uint32_t(1)) == 31); 141 | REQUIRE(clz(std::uint32_t(2)) == 30); 142 | REQUIRE(clz(std::uint32_t(0xFFFF)) == 16); 143 | REQUIRE(clz(std::uint32_t(0xFFFF + 1)) == 15); 144 | REQUIRE(clz(std::uint32_t(-1)) == 0); // max value 145 | 146 | // 64 bits 147 | REQUIRE(clz(std::uint64_t(1)) == 63); 148 | REQUIRE(clz(std::uint64_t(2)) == 62); 149 | REQUIRE(clz(std::uint64_t(std::uint32_t(-1))) == 32); 150 | REQUIRE(clz(std::uint64_t(std::uint32_t(-1)) + 1) == 31); 151 | REQUIRE(clz(std::uint64_t(-1)) == 0); // max value") 152 | -------------------------------------------------------------------------------- /ext/counter.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | # checks for __COUNTER__ macro, a common extension that expands to incresing integral numbers, starting with 0 11 | comp_feature(counter "#include 12 | #define CONCAT_IMPL(x, y) x##y 13 | #define CONCAT(x, y) CONCAT_IMPL(x, y) 14 | int CONCAT(a, __COUNTER__); 15 | char CONCAT(a, __COUNTER__); 16 | int main() {}" COMP_CPP98_FLAG) 17 | -------------------------------------------------------------------------------- /ext/ctz.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(ctz 11 | "#include 12 | 13 | template 14 | struct foo {}; 15 | 16 | int main() 17 | { 18 | int a = __builtin_ctz(4); 19 | int b = __builtin_ctzl(4); 20 | int c = __builtin_ctzll(4); 21 | 22 | // require constant expression 23 | foo<__builtin_ctz(4)> f; 24 | }" COMP_CPP11_FLAG) 25 | comp_workaround(ctz 26 | " 27 | #include 28 | 29 | // a function ctz() that returns the number of trailing zeros in an integer 30 | // undefined for input value 0! 31 | // * if builtin available: overloaded for each builtin version 32 | // * otherwise: binary search implementation w/ lookup table for last 4 bits, overloaded for each fixed-sized integers 33 | namespace ${COMP_NAMESPACE} 34 | { 35 | #if ${COMP_PREFIX}HAS_CTZ 36 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(unsigned int x) 37 | { 38 | return __builtin_ctz(x); 39 | } 40 | 41 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(unsigned long x) 42 | { 43 | return __builtin_ctzl(x); 44 | } 45 | 46 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(unsigned long long x) 47 | { 48 | return __builtin_ctzll(x); 49 | } 50 | #else 51 | namespace detail 52 | { 53 | ${COMP_PREFIX}CONSTEXPR char ctz_lookup[16] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; 54 | 55 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz_base(std::uint8_t higher, std::uint8_t lower) 56 | { 57 | return lower ? ctz_lookup[lower] : 4 + ctz_lookup[higher]; 58 | } 59 | } 60 | 61 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(std::uint8_t x) 62 | { 63 | return detail::ctz_base(x >> 4, x & 0x0Fu); 64 | } 65 | 66 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(std::uint16_t x) 67 | { 68 | return x & 0xFFu ? ctz(std::uint8_t(x & 0xFFu)) : 8 + ctz(std::uint8_t(x >> 8)); 69 | } 70 | 71 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(std::uint32_t x) 72 | { 73 | return x & 0xFFFFu ? ctz(std::uint16_t(x & 0xFFFFu)) : 16 + ctz(std::uint16_t(x >> 16)); 74 | } 75 | 76 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned ctz(std::uint64_t x) 77 | { 78 | return x & 0xFFFFFFFFul ? ctz(std::uint32_t(x & 0xFFFFFFFFul)) : 32 + ctz(std::uint32_t(x >> 32)); 79 | } 80 | #endif 81 | }" COMP_CPP11_FLAG cpp11_lang/constexpr) 82 | 83 | comp_unit_test(ctz 84 | "#include " 85 | " 86 | using ${COMP_NAMESPACE}::ctz; 87 | 88 | REQUIRE(ctz(1u) == 0); 89 | REQUIRE(ctz(2u) == 1); 90 | REQUIRE(ctz(3u) == 0); 91 | REQUIRE(ctz(4u) == 2); 92 | 93 | REQUIRE(ctz(255u) == 0); 94 | REQUIRE(ctz(256u) == 8); 95 | REQUIRE(ctz(257u) == 0); 96 | 97 | REQUIRE(ctz(std::uint32_t(-1)) == 0); 98 | REQUIRE(ctz(std::uint64_t(std::uint32_t(-1)) + 1) == 32); 99 | ") 100 | -------------------------------------------------------------------------------- /ext/expect.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(expect 11 | "#include 12 | 13 | int main() 14 | { 15 | if (__builtin_expect(true, true)) 16 | ; 17 | }" COMP_CPP98_FLAG) 18 | 19 | comp_workaround(expect 20 | "#ifndef ${COMP_PREFIX}EXPECT 21 | #if ${COMP_PREFIX}HAS_EXPECT 22 | #define ${COMP_PREFIX}EXPECT(expr, value) __builtin_expect((expr), value) 23 | #else 24 | #define ${COMP_PREFIX}EXPECT(expr, value) expr 25 | #endif 26 | #endif 27 | 28 | #define ${COMP_PREFIX}LIKELY(expr) ${COMP_PREFIX}EXPECT(expr, true) 29 | #define ${COMP_PREFIX}UNLIKELY(expr) ${COMP_PREFIX}EXPECT(expr, false) 30 | " COMP_CPP98_FLAG) 31 | -------------------------------------------------------------------------------- /ext/extension.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(extension 11 | "#include 12 | 13 | int main() 14 | { 15 | __extension__ int x; 16 | }" COMP_CPP98_FLAG) 17 | comp_workaround(extension 18 | "#ifndef ${COMP_PREFIX}EXTENSION 19 | #if ${COMP_PREFIX}HAS_EXTENSION 20 | #define ${COMP_PREFIX}EXTENSION __extension__ 21 | #else 22 | #define ${COMP_PREFIX}EXTENSION 23 | #endif 24 | #endif" COMP_CPP98_FLAG) 25 | -------------------------------------------------------------------------------- /ext/fallthrough.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(fallthrough 11 | "#include 12 | 13 | int main() 14 | { 15 | int a = 0; 16 | switch (3) 17 | { 18 | case 2: 19 | ++a; 20 | [[clang::fallthrough]]; 21 | case 3: 22 | ++a; 23 | break; 24 | } 25 | }" COMP_CPP11_FLAG) 26 | comp_workaround(fallthrough 27 | "#ifndef ${COMP_PREFIX}FALLTHROUGH 28 | #if ${COMP_PREFIX}HAS_FALLTHROUGH 29 | #define ${COMP_PREFIX}FALLTHROUGH [[clang::fallthrough]] 30 | #else 31 | #define ${COMP_PREFIX}FALLTHROUGH 32 | #endif 33 | #endif" COMP_CPP11_FLAG) 34 | -------------------------------------------------------------------------------- /ext/has_include.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(has_include "#include 11 | #if !__has_include() 12 | #error \"not supported\" 13 | #endif 14 | int main() {}" COMP_CPP98_FLAG) 15 | comp_workaround(has_include 16 | "#ifndef ${COMP_PREFIX}HAS_INCLUDE 17 | #if ${COMP_PREFIX}HAS_HAS_INCLUDE 18 | #define ${COMP_PREFIX}HAS_INCLUDE(x) __has_include(x) 19 | #else 20 | #define ${COMP_PREFIX}HAS_INCLUDE(x) 0 21 | #endif 22 | #endif" COMP_CPP98_FLAG) 23 | -------------------------------------------------------------------------------- /ext/int128.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(int128 11 | "#include 12 | 13 | int main() 14 | { 15 | __int128 i; 16 | unsigned __int128 u; 17 | }" COMP_CPP98_FLAG) 18 | comp_workaround(int128 19 | "namespace ${COMP_NAMESPACE} 20 | { 21 | #if ${COMP_PREFIX}HAS_INT128 22 | ${COMP_PREFIX}EXTENSION typedef __int128 int128_t; 23 | ${COMP_PREFIX}EXTENSION typedef unsigned __int128 uint128_t; 24 | #endif 25 | }" COMP_CPP98_FLAG ext/extension) 26 | -------------------------------------------------------------------------------- /ext/popcount.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(popcount 11 | "#include 12 | 13 | template 14 | struct foo {}; 15 | 16 | int main() 17 | { 18 | int a = __builtin_popcount(4); 19 | int b = __builtin_popcountl(4); 20 | int c = __builtin_popcountll(4); 21 | 22 | // require constant expression 23 | foo<__builtin_popcount(4)> f; 24 | }" COMP_CPP11_FLAG) 25 | comp_workaround(popcount 26 | " 27 | #include 28 | 29 | // a function popcount() that returns the number of 1-bits in an integer 30 | // * if builtin available: overloaded for each builtin version 31 | // * otherwise: bit-hack version, overloaded for uint32_t and uint64_t 32 | namespace ${COMP_NAMESPACE} 33 | { 34 | #if ${COMP_PREFIX}HAS_POPCOUNT 35 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned popcount(unsigned int x) 36 | { 37 | return __builtin_popcount(x); 38 | } 39 | 40 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned popcount(unsigned long x) 41 | { 42 | return __builtin_popcountl(x); 43 | } 44 | 45 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned popcount(unsigned long long x) 46 | { 47 | return __builtin_popcountll(x); 48 | } 49 | #else 50 | // warning: ugly bit hacks incoming 51 | // adapted from Hacker's Delight, p. 66, and https://en.wikipedia.org/wiki/Hamming_weight, popcount_2 52 | 53 | namespace detail 54 | { 55 | // step 1) 56 | // look at each pair of bits and put count of ones there 57 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint32_t popcount_2er(std::uint32_t x) 58 | { 59 | return x - ((x >> 1) & 0x55555555u); 60 | } 61 | 62 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t popcount_2er(std::uint64_t x) 63 | { 64 | return x - ((x >> 1) & 0x5555555555555555u); 65 | } 66 | 67 | // step 2) 68 | // look at each 4er pack of bits and put count of ones there 69 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint32_t popcount_4er(std::uint32_t x) 70 | { 71 | return (x & 0x33333333u) + ((x >> 2) & 0x33333333u); 72 | } 73 | 74 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t popcount_4er(std::uint64_t x) 75 | { 76 | return (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); 77 | } 78 | 79 | // step 3) 80 | // look at each 8er pack of bits and put count of ones there 81 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint32_t popcount_8er(std::uint32_t x) 82 | { 83 | return (x + (x >> 4)) & 0x0F0F0F0Fu; 84 | } 85 | 86 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t popcount_8er(std::uint64_t x) 87 | { 88 | return (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu; 89 | } 90 | 91 | // step 4) 92 | // look at each 16er pack of bits and put count of ones there 93 | template 94 | ${COMP_PREFIX}CONSTEXPR_FNC T popcount_16er(T x) 95 | { 96 | return x + (x >> 8); 97 | } 98 | 99 | // step 5) 100 | // look at each 32er pack of bits and put count of ones there 101 | template 102 | ${COMP_PREFIX}CONSTEXPR_FNC T popcount_32er(T x) 103 | { 104 | return x + (x >> 16); 105 | } 106 | 107 | // performs step 1-5 108 | template 109 | ${COMP_PREFIX}CONSTEXPR_FNC T popcount_upto_32er(T x) 110 | { 111 | return popcount_32er(popcount_16er(popcount_8er(popcount_4er(popcount_2er(x))))); 112 | } 113 | 114 | // step 6) (64bit only) 115 | // look at each 64er pack of bits and put count of ones there 116 | ${COMP_PREFIX}CONSTEXPR_FNC std::uint64_t popcount_64er(std::uint64_t x) 117 | { 118 | return x + (x >> 32); 119 | } 120 | } 121 | 122 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned popcount(std::uint32_t x) 123 | { 124 | // count bits and mask of higher bits 125 | return detail::popcount_upto_32er(x) & 0x3Fu; 126 | } 127 | 128 | ${COMP_PREFIX}CONSTEXPR_FNC unsigned popcount(std::uint64_t x) 129 | { 130 | // count bits (including 64er) and mask of higher bits 131 | return detail::popcount_64er(detail::popcount_upto_32er(x)) & 0x7Fu; 132 | } 133 | #endif 134 | }" COMP_CPP11_FLAG cpp11_lang/constexpr) 135 | 136 | comp_unit_test(popcount 137 | "" 138 | " 139 | using ${COMP_NAMESPACE}::popcount; 140 | 141 | REQUIRE(popcount(0u) == 0); 142 | REQUIRE(popcount(1u) == 1); 143 | REQUIRE(popcount(2u) == 1); 144 | REQUIRE(popcount(3u) == 2); 145 | REQUIRE(popcount(4u) == 1); 146 | 147 | REQUIRE(popcount(255u) == 8); 148 | REQUIRE(popcount(256u) == 1); 149 | 150 | REQUIRE(popcount(std::uint32_t(-1)) == 32); 151 | REQUIRE(popcount(std::uint64_t(std::uint32_t(-1)) + 1) == 1); 152 | REQUIRE(popcount(std::uint64_t(-1)) == 64); 153 | ") 154 | -------------------------------------------------------------------------------- /ext/pretty_function.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(pretty_function "#include 11 | int main() {(void)__PRETTY_FUNCTION__;}" 12 | COMP_CPP98_FLAG) 13 | comp_workaround(pretty_function 14 | "#ifndef ${COMP_PREFIX}PRETTY_FUNCTION 15 | #if ${COMP_PREFIX}HAS_PRETTY_FUNCTION || defined(__GNUC__) 16 | #define ${COMP_PREFIX}PRETTY_FUNCTION __PRETTY_FUNCTION__ 17 | #elif defined(_MSC_VER) 18 | #define ${COMP_PREFIX}PRETTY_FUNCTION __FUNCSIG__ 19 | #else 20 | #error \"no __PRETTY_FUNCTION__ macro available\" 21 | #endif 22 | #endif" COMP_CPP98_FLAG) 23 | -------------------------------------------------------------------------------- /ext/unreachable.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(unreachable 11 | "#include 12 | 13 | int main() 14 | { 15 | __builtin_unreachable(); 16 | }" COMP_CPP98_FLAG) 17 | comp_workaround(unreachable 18 | "#ifndef ${COMP_PREFIX}UNREACHABLE 19 | #if ${COMP_PREFIX}HAS_UNREACHABLE 20 | #define ${COMP_PREFIX}UNREACHABLE __builtin_unreachable() 21 | #elif defined(_MSC_VER) 22 | #define ${COMP_PREFIX}UNREACHABLE __assume(0) 23 | #else 24 | #define ${COMP_PREFIX}UNREACHABLE 25 | #endif 26 | #endif 27 | " COMP_CPP98_FLAG) 28 | -------------------------------------------------------------------------------- /ext/unused.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(unused 11 | "#include 12 | 13 | int main() 14 | { 15 | // use GCC style attributes to get an error under MSVC 16 | __attribute__((__unused__)) int x; 17 | }" COMP_CPP98_FLAG) 18 | comp_workaround(unused 19 | "#ifndef ${COMP_PREFIX}UNUSED 20 | #if ${COMP_PREFIX}HAS_UNUSED 21 | #define ${COMP_PREFIX}UNUSED __attribute__((__unused__)) 22 | #else 23 | #define ${COMP_PREFIX}UNUSED 24 | #endif 25 | #endif 26 | 27 | #define ${COMP_PREFIX}MARK_UNUSED(expr) do { if (false) (void)(expr); } while (false) 28 | " COMP_CPP98_FLAG) 29 | -------------------------------------------------------------------------------- /ts.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | comp_fetch_include(ts/any) 6 | comp_fetch_include(ts/apply) 7 | comp_fetch_include(ts/container_erasure) 8 | comp_fetch_include(ts/logical_operator_traits) 9 | comp_fetch_include(ts/make_array) 10 | comp_fetch_include(ts/not_fn) 11 | comp_fetch_include(ts/optional) 12 | comp_fetch_include(ts/pmr) 13 | comp_fetch_include(ts/string_view) -------------------------------------------------------------------------------- /ts/any.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(any 11 | "#include 12 | 13 | int main() 14 | { 15 | std::experimental::any a(5); 16 | 17 | int i = std::experimental::any_cast(a); 18 | }" COMP_CPP14_FLAG) 19 | -------------------------------------------------------------------------------- /ts/apply.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(apply 11 | "#include 12 | #include 13 | 14 | int a(int, int) {return 0;} 15 | 16 | int main() 17 | { 18 | std::tuple t; 19 | int val = std::experimental::apply(a, t); 20 | }" COMP_CPP14_FLAG) 21 | comp_workaround(apply 22 | "#include 23 | #include 24 | 25 | #if ${COMP_PREFIX}HAS_APPLY 26 | #include 27 | #endif 28 | 29 | namespace ${COMP_NAMESPACE} 30 | { 31 | #if ${COMP_PREFIX}HAS_APPLY 32 | using std::experimental::apply; 33 | #else 34 | #define ${COMP_PREFIX}DETAIL_AUTO_RETURN(...) decltype(__VA_ARGS__) {return (__VA_ARGS__);} 35 | 36 | namespace detail 37 | { 38 | template 39 | ${COMP_PREFIX}CONSTEXPR auto apply(F &&f, Tuple &&t, ${COMP_NAMESPACE}::index_sequence) 40 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(${COMP_NAMESPACE}::invoke(std::forward(f), std::get(std::forward(t))...)) 41 | } 42 | 43 | template 44 | ${COMP_PREFIX}CONSTEXPR auto apply(F &&f, Tuple &&t) 45 | -> ${COMP_PREFIX}DETAIL_AUTO_RETURN(detail::apply(std::forward(f), std::forward(t),${COMP_NAMESPACE}::make_index_sequence::type>::value>{})) 46 | 47 | #undef ${COMP_PREFIX}DETAIL_AUTO_RETURN 48 | #endif 49 | }" COMP_CPP11_FLAG cpp11_lang/constexpr cpp14_lib/integer_sequence cpp17_lib/invoke) 50 | 51 | # rudimentary test to force instantiation 52 | comp_unit_test(apply 53 | " 54 | #include 55 | 56 | void apply_test(int a, int b, std::string str) 57 | { 58 | REQUIRE(a == 0); 59 | REQUIRE(b == 1); 60 | REQUIRE(str == \"abc\"); 61 | } 62 | " 63 | " 64 | std::tuple tuple = std::make_tuple(0, 1, \"abc\"); 65 | ${COMP_NAMESPACE}::apply(apply_test, tuple); 66 | ") -------------------------------------------------------------------------------- /ts/container_erasure.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(container_erasure 11 | "#include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | bool f() {return true;} 23 | 24 | int main() 25 | { 26 | std::vector vec; 27 | std::experimental::erase(vec, 3); 28 | std::experimental::erase_if(vec, f); 29 | }" COMP_CPP17_FLAG) 30 | comp_workaround(container_erasure 31 | " 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #if ${COMP_PREFIX}HAS_CONTAINER_ERASURE 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #else 53 | #include 54 | #endif 55 | 56 | namespace ${COMP_NAMESPACE} 57 | { 58 | #if ${COMP_PREFIX}HAS_CONTAINER_ERASURE 59 | using std::experimental::erase; 60 | using std::experimental::erase_if; 61 | #else 62 | template 63 | void erase_if(std::basic_string &c, Pred p) 64 | { 65 | c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 66 | } 67 | 68 | template 69 | void erase_if(std::deque &c, Pred p) 70 | { 71 | c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 72 | } 73 | 74 | template 75 | void erase_if(std::forward_list &c, Pred p) 76 | { 77 | c.remove_if(p); 78 | } 79 | 80 | template 81 | void erase_if(std::list &c, Pred p) 82 | { 83 | c.remove_if(p); 84 | } 85 | 86 | template 87 | void erase_if(std::vector &c, Pred p) 88 | { 89 | c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 90 | } 91 | 92 | namespace detail 93 | { 94 | template 95 | void erase_if_loop(Container &c, Pred p) 96 | { 97 | typename Container::iterator i = c.begin(), last = c.end(); 98 | while (i != last) 99 | { 100 | if (p(*i)) 101 | i = c.erase(i); 102 | else 103 | ++i; 104 | } 105 | } 106 | } 107 | 108 | template 109 | void erase_if(std::map &c, Pred p) 110 | { 111 | detail::erase_if_loop(c, p); 112 | } 113 | 114 | template 115 | void erase_if(std::multimap &c, Pred p) 116 | { 117 | detail::erase_if_loop(c, p); 118 | } 119 | 120 | template 121 | void erase_if(std::set &c, Pred p) 122 | { 123 | detail::erase_if_loop(c, p); 124 | } 125 | 126 | template 127 | void erase_if(std::multiset &c, Pred p) 128 | { 129 | detail::erase_if_loop(c, p); 130 | } 131 | 132 | template 133 | void erase_if(std::unordered_map &c, Pred p) 134 | { 135 | detail::erase_if_loop(c, p); 136 | } 137 | 138 | template 139 | void erase_if(std::unordered_multimap &c, Pred p) 140 | { 141 | detail::erase_if_loop(c, p); 142 | } 143 | 144 | template 145 | void erase_if(std::unordered_set &c, Pred p) 146 | { 147 | detail::erase_if_loop(c, p); 148 | } 149 | 150 | template 151 | void erase_if(std::unordered_multiset &c, Pred p) 152 | { 153 | detail::erase_if_loop(c, p); 154 | } 155 | 156 | template 157 | void erase(std::basic_string &c, const U &value) 158 | { 159 | c.erase(std::remove(c.begin(), c.end(), value), c.end()); 160 | } 161 | 162 | template 163 | void erase(std::deque &c, const U &value) 164 | { 165 | c.erase(std::remove(c.begin(), c.end(), value), c.end()); 166 | } 167 | 168 | namespace detail 169 | { 170 | template 171 | struct erase_value 172 | { 173 | const U *ptr; 174 | 175 | template 176 | bool operator()(const T &val) const 177 | { 178 | return val == *ptr; 179 | } 180 | }; 181 | } 182 | 183 | template 184 | void erase(std::forward_list &c, const U &value) 185 | { 186 | c.remove_if(detail::erase_value{&value}); 187 | } 188 | 189 | template 190 | void erase(std::list &c, const U &value) 191 | { 192 | c.remove_if(detail::erase_value{&value}); 193 | } 194 | 195 | template 196 | void erase(std::vector &c, const U &value) 197 | { 198 | c.erase(std::remove(c.begin(), c.end(), value), c.end()); 199 | } 200 | 201 | template 202 | void erase(std::map &c, const U &value) 203 | { 204 | detail::erase_if_loop(c, detail::erase_value{&value}); 205 | } 206 | 207 | template 208 | void erase(std::multimap &c, const U &value) 209 | { 210 | detail::erase_if_loop(c, detail::erase_value{&value}); 211 | } 212 | 213 | template 214 | void erase(std::set &c, const U &value) 215 | { 216 | detail::erase_if_loop(c, detail::erase_value{&value}); 217 | } 218 | 219 | template 220 | void erase(std::multiset &c, const U &value) 221 | { 222 | detail::erase_if_loop(c, detail::erase_value{&value}); 223 | } 224 | 225 | template 226 | void erase(std::unordered_map &c, const U &value) 227 | { 228 | detail::erase_if_loop(c, detail::erase_value{&value}); 229 | } 230 | 231 | template 232 | void erase(std::unordered_multimap &c, const U &value) 233 | { 234 | detail::erase_if_loop(c, detail::erase_value{&value}); 235 | } 236 | 237 | template 238 | void erase(std::unordered_set &c, const U &value) 239 | { 240 | detail::erase_if_loop(c, detail::erase_value{&value}); 241 | } 242 | 243 | template 244 | void erase(std::unordered_multiset &c, const U &value) 245 | { 246 | detail::erase_if_loop(c, detail::erase_value{&value}); 247 | } 248 | #endif 249 | }" COMP_CPP11_FLAG) 250 | -------------------------------------------------------------------------------- /ts/logical_operator_traits.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(logical_operator_traits 11 | "#include 12 | #include 13 | 14 | struct foo : std::true_type 15 | {}; 16 | 17 | int main() 18 | { 19 | std:;experimental::conjunction c; 20 | }" COMP_CPP17_FLAG) 21 | comp_workaround(logical_operator_traits 22 | "#include 23 | 24 | #if ${COMP_PREFIX}HAS_LOGICAL_OPERATOR_TRAITS 25 | #include 26 | #endif 27 | 28 | namespace ${COMP_NAMESPACE} 29 | { 30 | #if ${COMP_PREFIX}HAS_LOGICAL_OPERATOR_TRAITS 31 | using std::experimental::conjunction; 32 | using std::experimental::disjunction; 33 | using std::experimental::negation; 34 | #else 35 | template 36 | struct negation : std::integral_constant {}; 37 | 38 | // conjunction 39 | template 40 | struct conjunction; 41 | 42 | template <> 43 | struct conjunction<> 44 | : std::true_type {}; 45 | 46 | template 47 | struct conjunction 48 | : B1 {}; 49 | 50 | template 51 | struct conjunction 52 | : std::conditional>::type {}; 53 | 54 | // disjunction 55 | template 56 | struct disjunction; 57 | 58 | template <> 59 | struct disjunction<> 60 | : std::false_type {}; 61 | 62 | template 63 | struct disjunction 64 | : B1 {}; 65 | 66 | template 67 | struct disjunction 68 | : std::conditional, B1> {}; 69 | #endif 70 | }" COMP_CPP11_FLAG) 71 | -------------------------------------------------------------------------------- /ts/make_array.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(make_array 11 | "#include 12 | #include 13 | 14 | int main() 15 | { 16 | std::array arr = std::experimental::make_array(1, 2, 3, 4, 5); 17 | int arr2[] = {1, 2, 3}; 18 | std::array arr3 = std::experimental::to_array(arr2); 19 | }" COMP_CPP17_FLAG) 20 | comp_workaround(make_array 21 | "#include 22 | #include 23 | #include 24 | 25 | #if ${COMP_PREFIX}HAS_MAKE_ARRAY 26 | #include 27 | #endif 28 | 29 | namespace ${COMP_NAMESPACE} 30 | { 31 | #if ${COMP_PREFIX}HAS_MAKE_ARRAY 32 | using std::experimental::make_array; 33 | using std::experimental::to_array; 34 | #else 35 | // based on cppreference.com 36 | namespace detail 37 | { 38 | template 39 | struct no_ref_wrapper : std::true_type {}; 40 | 41 | template 42 | struct no_ref_wrapper> : std::false_type{}; 43 | 44 | template 45 | struct return_type 46 | { 47 | typedef D type; 48 | }; 49 | 50 | template 51 | struct return_type 52 | { 53 | static_assert(${COMP_NAMESPACE}::conjunction::type>...>::value, 54 | \"make_array: cannot deduce type if passed reference wrapper\"); 55 | 56 | typedef typename std::common_type::type type; 57 | }; 58 | } 59 | 60 | template 61 | ${COMP_PREFIX}CONSTEXPR std::array::type, sizeof...(Ts)> 62 | make_array(Ts&&... ts) 63 | { 64 | return {std::forward(ts)...}; 65 | } 66 | 67 | namespace detail 68 | { 69 | template 70 | ${COMP_PREFIX}CONSTEXPR std::array::type, N> 71 | to_array(T(&arr)[N], ${COMP_NAMESPACE}::index_sequence) 72 | { 73 | return {{ arr[Is]... }}; 74 | } 75 | } 76 | 77 | template 78 | ${COMP_PREFIX}CONSTEXPR std::array::type, N> 79 | to_array(T(&arr)[N]) 80 | { 81 | return detail::to_array(arr, ${COMP_NAMESPACE}::make_index_sequence{}); 82 | } 83 | #endif 84 | }" COMP_CPP11_FLAG cpp11_lang/constexpr cpp14_lib/integer_sequence ts/logical_operator_traits) 85 | 86 | comp_unit_test(make_array 87 | "" 88 | " 89 | // just instantiate functions 90 | std::array arr = ${COMP_NAMESPACE}::make_array(1, 2, 3, 4, 5); 91 | int arr2[] = {1, 2, 3}; 92 | std::array arr3 = ${COMP_NAMESPACE}::to_array(arr2); 93 | ") 94 | -------------------------------------------------------------------------------- /ts/not_fn.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(not_fn 11 | "#include 12 | 13 | bool f() {return true;} 14 | 15 | int main() 16 | { 17 | bool val = std::experimental::not_fn(f)(); 18 | }" COMP_CPP17_FLAG) 19 | comp_workaround(not_fn 20 | "#include 21 | 22 | #if ${COMP_PREFIX}HAS_NOT_FN 23 | #include 24 | #endif 25 | 26 | namespace ${COMP_NAMESPACE} 27 | { 28 | #if ${COMP_PREFIX}HAS_NOT_FN 29 | using std::experimental::not_fn; 30 | #else 31 | namespace detail 32 | { 33 | template 34 | struct notter 35 | { 36 | F f; 37 | 38 | template 39 | auto operator()(Args&&... args) 40 | -> decltype(!${COMP_NAMESPACE}::invoke(f, std::forward(args)...)) 41 | { 42 | return !${COMP_NAMESPACE}::invoke(f, std::forward(args)...); 43 | } 44 | }; 45 | } 46 | 47 | template 48 | detail::notter::type> not_fn(F &&f) 49 | { 50 | return {std::forward(f)}; 51 | } 52 | #endif 53 | }" COMP_CPP11_FLAG cpp17_lib/invoke) 54 | 55 | comp_unit_test(not_fn 56 | "bool not_fn_test(int a) {return a % 2 == 0;}" 57 | " 58 | REQUIRE(not_fn_test(2)); 59 | REQUIRE(!not_fn_test(3)); 60 | 61 | auto f = ${COMP_NAMESPACE}::not_fn(not_fn_test); 62 | REQUIRE(!f(2)); 63 | REQUIRE(f(3));") 64 | -------------------------------------------------------------------------------- /ts/optional.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(optional 11 | "#include 12 | 13 | int main() 14 | { 15 | using namespace std::experimental; 16 | optional opt(nullopt); 17 | }" COMP_CPP14_FLAG) 18 | -------------------------------------------------------------------------------- /ts/pmr.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(pmr 11 | "#include 12 | 13 | int main() 14 | { 15 | using namespace std::experimental::pmr; 16 | 17 | memory_resource* res = get_default_resource(); 18 | polymorphic_allocator alloc(res); 19 | } 20 | " COMP_CPP14_FLAG) 21 | comp_workaround(pmr 22 | "#include 23 | 24 | #if ${COMP_PREFIX}HAS_PMR 25 | #include 26 | #endif 27 | 28 | namespace ${COMP_NAMESPACE} 29 | { 30 | #if ${COMP_PREFIX}HAS_PMR 31 | using std::experimental::pmr::memory_resource; 32 | #else 33 | // see N3916 for documentation 34 | class memory_resource 35 | { 36 | static const std::size_t max_alignment = ${COMP_PREFIX}ALIGNOF(max_align_t); 37 | public: 38 | virtual ~memory_resource() ${COMP_PREFIX}NOEXCEPT {} 39 | 40 | void* allocate(std::size_t bytes, std::size_t alignment = max_alignment) 41 | { 42 | return do_allocate(bytes, alignment); 43 | } 44 | 45 | void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_alignment) 46 | { 47 | do_deallocate(p, bytes, alignment); 48 | } 49 | 50 | bool is_equal(const memory_resource& other) const ${COMP_PREFIX}NOEXCEPT 51 | { 52 | return do_is_equal(other); 53 | } 54 | 55 | protected: 56 | virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0; 57 | 58 | virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0; 59 | 60 | virtual bool do_is_equal(const memory_resource& other) const ${COMP_PREFIX}NOEXCEPT = 0; 61 | }; 62 | 63 | inline bool operator==(const memory_resource& a, const memory_resource& b) ${COMP_PREFIX}NOEXCEPT 64 | { 65 | return &a == &b || a.is_equal(b); 66 | } 67 | 68 | inline bool operator!=(const memory_resource& a, const memory_resource& b) ${COMP_PREFIX}NOEXCEPT 69 | { 70 | return !(a == b); 71 | } 72 | #endif 73 | }" COMP_CPP11_FLAG cpp11_lang/alignof cpp11_lang/noexcept cpp11_lib/max_align_t) 74 | -------------------------------------------------------------------------------- /ts/string_view.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015-2016 Jonathan Müller 2 | # This file is subject to the license terms in the LICENSE file 3 | # found in the top-level directory of this distribution. 4 | 5 | if(NOT COMP_API_VERSION) 6 | message(FATAL_ERROR "needs newer comp_base.cmake version") 7 | endif() 8 | comp_api_version(1) 9 | 10 | comp_feature(string_view 11 | "#include 12 | 13 | int main() 14 | { 15 | std::experimental::string_view view(\"Hello World!\"); 16 | }" COMP_CPP14_FLAG) 17 | --------------------------------------------------------------------------------