diff --git a/.travis.yml b/.travis.yml index 2131229f6..8713d9e16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -97,6 +97,14 @@ matrix: ########################################################################## # Build with variations in the configuration ########################################################################## + # With C++17 instead of C++14, on Clang + - env: UNIT_TESTS=true COMPILER=default BOOST_VERSION=default CMAKE_OPTIONS="-DBOOST_HANA_ENABLE_CPP17=ON" + addons: *defaults + + # With C++17 instead of C++14, on GCC + - env: UNIT_TESTS=true COMPILER=g++-6 BOOST_VERSION=default CMAKE_OPTIONS="-DBOOST_HANA_ENABLE_CPP17=ON" + addons: { apt: { packages: ["g++-6", "valgrind"], sources: ["ubuntu-toolchain-r-test"] } } + # Without concept checks - env: UNIT_TESTS=true COMPILER=default BOOST_VERSION=default CMAKE_OPTIONS="-DBOOST_HANA_ENABLE_CONCEPT_CHECKS=OFF" addons: *defaults diff --git a/CMakeLists.txt b/CMakeLists.txt index d20d07619..28dd29cbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,22 @@ cmake_minimum_required(VERSION 3.8) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +############################################################################## +# Setup CMake options +############################################################################## +option(BOOST_HANA_ENABLE_CONCEPT_CHECKS "Enable concept checking in the interface methods." ON) +option(BOOST_HANA_ENABLE_DEBUG_MODE "Enable Hana's debug mode." OFF) +option(BOOST_HANA_ENABLE_CPP17 "Build with C++17 instead of usual required C++ standard. Useful for testing." OFF) + +option(BOOST_HANA_ENABLE_STRING_UDL +"Enable the GNU extension allowing the special string literal operator\ + template, which enables the _s suffix for creating compile-time strings." ON) + +option(BOOST_HANA_ENABLE_EXCEPTIONS +"Build with exceptions enabled. Note that Hana does not make use of exceptions,\ + but this switch can be disabled when building the tests to assess that it is\ + really the case." ON) + ############################################################################## # Setup project @@ -31,14 +47,19 @@ include(CheckCxxCompilerSupport) # Setup the 'hana' header-only library target, along with its install target # and exports. ############################################################################## +include(CheckCXXCompilerFlag) add_library(hana INTERFACE) target_include_directories(hana INTERFACE "$" $) # With Clang on Windows, the -std=c++14 flag is incorrectly set and the compiler -# complains about the unkown option. TODO: Remove this workaround once the +# complains about the unknown option. TODO: Remove this workaround once the # underlying bug is fixed in CMake: https://gitlab.kitware.com/cmake/cmake/issues/17015 if (NOT (MSVC AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")) - target_compile_features(hana INTERFACE cxx_std_14) + if (BOOST_HANA_ENABLE_CPP17) + target_compile_features(hana INTERFACE cxx_std_17) + else() + target_compile_features(hana INTERFACE cxx_std_14) + endif() endif() # Export the `hana` library into a HanaConfig.cmake file @@ -52,25 +73,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/hana.pc" DESTINATION lib/pkgconfig) ############################################################################## -# Setup CMake options -############################################################################## -option(BOOST_HANA_ENABLE_CONCEPT_CHECKS "Enable concept checking in the interface methods." ON) -option(BOOST_HANA_ENABLE_DEBUG_MODE "Enable Hana's debug mode." OFF) - -option(BOOST_HANA_ENABLE_STRING_UDL -"Enable the GNU extension allowing the special string literal operator\ - template, which enables the _s suffix for creating compile-time strings." ON) - -option(BOOST_HANA_ENABLE_EXCEPTIONS -"Build with exceptions enabled. Note that Hana does not make use of exceptions,\ - but this switch can be disabled when building the tests to assess that it is\ - really the case." ON) - - -############################################################################## # Function to setup common compiler flags on tests and examples ############################################################################## -include(CheckCXXCompilerFlag) function(boost_hana_set_test_properties target) target_link_libraries(${target} PRIVATE hana) set_target_properties(${target} PROPERTIES CXX_EXTENSIONS NO) diff --git a/example/chain.cpp b/example/chain.cpp index 04a3fe41e..0e7850b74 100644 --- a/example/chain.cpp +++ b/example/chain.cpp @@ -28,7 +28,7 @@ struct Person { }; int main() { - Person john{30}; + constexpr Person john{30}; // Can't dereference a non-pointer. BOOST_HANA_CONSTANT_CHECK(f(john) == hana::nothing); diff --git a/example/cppcon_2014/functor.cpp b/example/cppcon_2014/functor.cpp index b447002ca..b616a5241 100644 --- a/example/cppcon_2014/functor.cpp +++ b/example/cppcon_2014/functor.cpp @@ -15,7 +15,7 @@ using namespace cppcon; int main() { // transform { - auto m = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto m = matrix( row(1, hana::int_c<2>, 3), row(hana::int_c<4>, 5, 6), row(7, 8, hana::int_c<9>) diff --git a/example/cppcon_2014/matrix.cpp b/example/cppcon_2014/matrix.cpp index 3143459c5..0d5d020f1 100644 --- a/example/cppcon_2014/matrix.cpp +++ b/example/cppcon_2014/matrix.cpp @@ -13,7 +13,7 @@ using namespace cppcon; int main() { // transpose { - auto m = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto m = matrix( row(1, 2.2, '3'), row(4, '5', 6) ); @@ -30,7 +30,7 @@ int main() { // vector { - auto v = vector(1, '2', hana::int_c<3>, 4.2f); + BOOST_HANA_CONSTEXPR_LAMBDA auto v = vector(1, '2', hana::int_c<3>, 4.2f); BOOST_HANA_CONSTEXPR_CHECK(v.size() == 4ul); BOOST_HANA_CONSTEXPR_CHECK(v.nrows() == 4ul); BOOST_HANA_CONSTEXPR_CHECK(v.ncolumns() == 1ul); @@ -38,7 +38,7 @@ int main() { // matrix.at { - auto m = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto m = matrix( row(1, '2', 3), row('4', hana::char_c<'5'>, 6), row(hana::int_c<7>, '8', 9.3) @@ -58,7 +58,7 @@ int main() { // size, ncolumns, nrows { - auto m = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto m = matrix( row(1, '2', 3), row('4', hana::char_c<'5'>, 6) ); diff --git a/example/cppcon_2014/ring.cpp b/example/cppcon_2014/ring.cpp index 718539ccc..9d06400de 100644 --- a/example/cppcon_2014/ring.cpp +++ b/example/cppcon_2014/ring.cpp @@ -16,12 +16,12 @@ using namespace cppcon; int main() { // mult { - auto a = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto a = matrix( row(1, 2, 3), row(4, 5, 6) ); - auto b = matrix( + BOOST_HANA_CONSTEXPR_LAMBDA auto b = matrix( row(1, 2), row(3, 4), row(5, 6) diff --git a/example/functional/fix.cpp b/example/functional/fix.cpp index 8547a8d1a..62ad03742 100644 --- a/example/functional/fix.cpp +++ b/example/functional/fix.cpp @@ -8,7 +8,7 @@ namespace hana = boost::hana; -BOOST_HANA_CONSTEXPR_LAMBDA auto factorial = hana::fix([](auto fact, auto n) -> int { +BOOST_HANA_CONSTEXPR_STATELESS_LAMBDA auto factorial = hana::fix([](auto fact, auto n) -> int { if (n == 0) return 1; else return n * fact(n - 1); }); diff --git a/example/integral_constant.cpp b/example/integral_constant.cpp index c6eef44e3..aaad126da 100644 --- a/example/integral_constant.cpp +++ b/example/integral_constant.cpp @@ -44,7 +44,7 @@ BOOST_HANA_RUNTIME_CHECK(s == "xxxxxyyyyyzzzzz"); //! [times_higher_order] std::string s; -BOOST_HANA_CONSTEXPR_LAMBDA auto functions = hana::make_tuple( +auto functions = hana::make_tuple( [&] { s += "x"; }, [&] { s += "y"; }, [&] { s += "z"; } diff --git a/example/monadic_fold_left.cpp b/example/monadic_fold_left.cpp index 8a5373a3a..734c055e0 100644 --- a/example/monadic_fold_left.cpp +++ b/example/monadic_fold_left.cpp @@ -2,6 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) +#include #include #include #include @@ -41,6 +42,12 @@ struct common_type template using common_type_t = typename common_type::type; +BOOST_HANA_CONSTANT_CHECK( + builtin_common_t(hana::type_c, hana::type_c) + == + hana::just(hana::type_c) +); + static_assert(std::is_same< common_type_t, int diff --git a/example/optional/applicative.complex.cpp b/example/optional/applicative.complex.cpp index 72dc9f012..f8eb84a73 100644 --- a/example/optional/applicative.complex.cpp +++ b/example/optional/applicative.complex.cpp @@ -39,6 +39,7 @@ BOOST_HANA_CONSTEXPR_LAMBDA auto evaluate = hana::ap(function, digit, dig int main() { BOOST_HANA_CONSTEXPR_CHECK(evaluate<'1', '+', '2'> == hana::just(1 + 2)); + BOOST_HANA_CONSTEXPR_CHECK(evaluate<'4', '-', '2'> == hana::just(4 - 2)); BOOST_HANA_CONSTANT_CHECK(evaluate<'?', '+', '2'> == hana::nothing); BOOST_HANA_CONSTANT_CHECK(evaluate<'1', '?', '2'> == hana::nothing); diff --git a/example/optional/sfinae_friendly_metafunctions.cpp b/example/optional/sfinae_friendly_metafunctions.cpp index 1db88f3be..392154b39 100644 --- a/example/optional/sfinae_friendly_metafunctions.cpp +++ b/example/optional/sfinae_friendly_metafunctions.cpp @@ -3,6 +3,7 @@ // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #include +#include #include #include #include @@ -29,9 +30,15 @@ auto common_type_impl = hana::sfinae([](auto t, auto u) -> hana::type< > { return {}; }); template -using common_type2 = decltype(common_type_impl(hana::type_c, hana::type_c)); +using common_type = decltype(common_type_impl(hana::type_c, hana::type_c)); -static_assert(!has_type>{}, ""); -static_assert(std::is_same::type, float>{}, ""); +BOOST_HANA_CONSTANT_CHECK( + common_type_impl(hana::type_c, hana::type_c) + == + hana::just(hana::type_c) +); + +static_assert(!has_type>{}, ""); +static_assert(std::is_same::type, float>{}, ""); int main() { } diff --git a/include/boost/hana/assert.hpp b/include/boost/hana/assert.hpp index e74691051..960310769 100644 --- a/include/boost/hana/assert.hpp +++ b/include/boost/hana/assert.hpp @@ -286,16 +286,35 @@ Distributed under the Boost Software License, Version 1.0. // BOOST_HANA_CONSTEXPR_CHECK and BOOST_HANA_CONSTEXPR_CHECK_MSG ////////////////////////////////////////////////////////////////////////////// -//! @ingroup group-assertions -//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by the -//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. +#if defined(BOOST_HANA_DOXYGEN_INVOKED) + //! @ingroup group-assertions + //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by + //! the `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. + //! For internal use only. +# define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) implementation-defined + + //! @ingroup group-assertions + //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the + //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. + //! For internal use only. +# define BOOST_HANA_CONSTEXPR_CHECK(...) implementation-defined + +#elif defined(BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA) + +# define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \ + static_assert(condition, message) \ +/**/ + +# define BOOST_HANA_CONSTEXPR_CHECK(...) \ + static_assert((__VA_ARGS__), BOOST_HANA_PP_STRINGIZE(__VA_ARGS__)) \ +/**/ + +#else + # define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \ BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \ /**/ -//! @ingroup group-assertions -//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the -//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. # define BOOST_HANA_CONSTEXPR_CHECK(...) \ BOOST_HANA_CONSTEXPR_CHECK_MSG( \ (__VA_ARGS__), \ @@ -303,4 +322,6 @@ Distributed under the Boost Software License, Version 1.0. ) \ /**/ +#endif + #endif // !BOOST_HANA_ASSERT_HPP diff --git a/include/boost/hana/cartesian_product.hpp b/include/boost/hana/cartesian_product.hpp index eaf8bb4d9..556c3b523 100644 --- a/include/boost/hana/cartesian_product.hpp +++ b/include/boost/hana/cartesian_product.hpp @@ -49,7 +49,7 @@ BOOST_HANA_NAMESPACE_BEGIN template struct cartesian_product_indices { static constexpr std::size_t total_length() { - std::size_t lengths[] = {Lengths...}; + std::size_t lengths[sizeof...(Lengths)] = {Lengths...}; std::size_t r = 1; for (std::size_t len: lengths) r *= len; @@ -59,7 +59,7 @@ BOOST_HANA_NAMESPACE_BEGIN static constexpr std::size_t length = total_length(); static constexpr auto indices_of(std::size_t i) { - constexpr std::size_t lengths[] = {Lengths...}; + constexpr std::size_t lengths[sizeof...(Lengths)] = {Lengths...}; constexpr std::size_t n = sizeof...(Lengths); detail::array result{}; for (std::size_t j = n; j--;) { diff --git a/include/boost/hana/config.hpp b/include/boost/hana/config.hpp index 6cf6ace71..bf70920b4 100644 --- a/include/boost/hana/config.hpp +++ b/include/boost/hana/config.hpp @@ -124,14 +124,21 @@ Distributed under the Boost Software License, Version 1.0. // Caveats and other compiler-dependent options ////////////////////////////////////////////////////////////////////////////// -// BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA enables some constructs requiring -// `constexpr` lambdas, which are not in the language (yet). -// Currently always disabled. +// `BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA` enables some constructs requiring +// `constexpr` lambdas, which are in the language starting with C++17. // -// BOOST_HANA_CONSTEXPR_LAMBDA expands to `constexpr` if constexpr lambdas +// Always disabled for now because Clang only has partial support for them +// (captureless lambdas only). +#if defined(__cplusplus) && __cplusplus > 201402L +# define BOOST_HANA_CONSTEXPR_STATELESS_LAMBDA constexpr +// # define BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA +#else +# define BOOST_HANA_CONSTEXPR_STATELESS_LAMBDA /* nothing */ +#endif + +// `BOOST_HANA_CONSTEXPR_LAMBDA` expands to `constexpr` if constexpr lambdas // are supported and to nothing otherwise. -#if 0 -# define BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA +#if defined(BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA) # define BOOST_HANA_CONSTEXPR_LAMBDA constexpr #else # define BOOST_HANA_CONSTEXPR_LAMBDA /* nothing */ diff --git a/include/boost/hana/detail/unpack_flatten.hpp b/include/boost/hana/detail/unpack_flatten.hpp index 0c65e803b..65cb3d950 100644 --- a/include/boost/hana/detail/unpack_flatten.hpp +++ b/include/boost/hana/detail/unpack_flatten.hpp @@ -25,7 +25,7 @@ BOOST_HANA_NAMESPACE_BEGIN namespace detail { template struct flatten_indices { // avoid empty arrays by appending 0 to `lengths` - static constexpr std::size_t lengths[] = {Lengths..., 0}; + static constexpr std::size_t lengths[sizeof...(Lengths) + 1] = {Lengths..., 0}; static constexpr auto flat_length = detail::accumulate(lengths, lengths + sizeof...(Lengths), 0); diff --git a/include/boost/hana/group.hpp b/include/boost/hana/group.hpp index b21cd6b5f..52a3d64f7 100644 --- a/include/boost/hana/group.hpp +++ b/include/boost/hana/group.hpp @@ -78,7 +78,7 @@ BOOST_HANA_NAMESPACE_BEGIN template struct group_indices { - static constexpr bool bs[] = {b...}; + static constexpr bool bs[sizeof...(b)] = {b...}; static constexpr std::size_t n_groups = detail::count(bs, bs + sizeof(bs), false) + 1; diff --git a/include/boost/hana/partition.hpp b/include/boost/hana/partition.hpp index fdea39bcf..e2131f423 100644 --- a/include/boost/hana/partition.hpp +++ b/include/boost/hana/partition.hpp @@ -49,9 +49,9 @@ BOOST_HANA_NAMESPACE_BEGIN namespace detail { template struct partition_indices { - static constexpr bool results[] = {B..., false}; // avoid empty array + static constexpr detail::array results{{B...}}; static constexpr std::size_t left_size = - detail::count(results, results + sizeof...(B), true); + detail::count(results.begin(), results.end(), true); static constexpr std::size_t right_size = sizeof...(B) - left_size; static constexpr auto compute_left() {