From 5478c540cb930b639cb0fd95f7a3a4c5914c6d69 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 10 Mar 2014 11:55:53 -0400 Subject: [PATCH] Add std::integer_sequence C++14 compatibility --- Builds/VisualStudio2013/beast.vcxproj | 8 + Builds/VisualStudio2013/beast.vcxproj.filters | 12 ++ beast/cxx14/cxx14.cpp | 20 +++ beast/cxx14/tests/integer_sequence.test.cpp | 113 ++++++++++++ beast/cxx14/utility.h | 169 ++++++++++++++++++ 5 files changed, 322 insertions(+) create mode 100644 beast/cxx14/cxx14.cpp create mode 100644 beast/cxx14/tests/integer_sequence.test.cpp create mode 100644 beast/cxx14/utility.h diff --git a/Builds/VisualStudio2013/beast.vcxproj b/Builds/VisualStudio2013/beast.vcxproj index 2da17674f..ca4bc0d47 100644 --- a/Builds/VisualStudio2013/beast.vcxproj +++ b/Builds/VisualStudio2013/beast.vcxproj @@ -144,6 +144,7 @@ + @@ -518,6 +519,13 @@ true true + + + true + true + true + true + true diff --git a/Builds/VisualStudio2013/beast.vcxproj.filters b/Builds/VisualStudio2013/beast.vcxproj.filters index 6fb476455..f28b074d1 100644 --- a/Builds/VisualStudio2013/beast.vcxproj.filters +++ b/Builds/VisualStudio2013/beast.vcxproj.filters @@ -309,6 +309,9 @@ {4b468051-9e97-4548-a5f0-469425c3b603} + + {1271ee71-5754-46ef-845b-84e53eed11c0} + @@ -1332,6 +1335,9 @@ beast\container + + beast\cxx14 + @@ -1919,6 +1925,12 @@ beast\container\tests + + beast\cxx14 + + + beast\cxx14\tests + diff --git a/beast/cxx14/cxx14.cpp b/beast/cxx14/cxx14.cpp new file mode 100644 index 000000000..592b7448d --- /dev/null +++ b/beast/cxx14/cxx14.cpp @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "tests/integer_sequence.test.cpp" diff --git a/beast/cxx14/tests/integer_sequence.test.cpp b/beast/cxx14/tests/integer_sequence.test.cpp new file mode 100644 index 000000000..2f1b0baab --- /dev/null +++ b/beast/cxx14/tests/integer_sequence.test.cpp @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "../utility.h" + +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { +namespace asio { + +class integer_sequence_Tests : public UnitTest +{ +public: + template + static + auto + extract (AtContainer const& t, + std::integer_sequence ) -> + decltype (std::make_tuple (std::get (t)...)) + { + return std::make_tuple (std::get (t)...); + } + + void runTest() + { + beginTestCase ("call"); + + // Code from + // http://llvm.org/svn/llvm-project/libcxx/trunk/test/utilities/intseq/intseq.general/integer_seq.pass.cpp + + // Make a couple of sequences + using int3 = std::make_integer_sequence; // generates int: 0,1,2 + using size7 = std::make_integer_sequence; // generates size_t: 0,1,2,3,4,5,6 + using size4 = std::make_index_sequence<4>; // generates size_t: 0,1,2,3 + using size2 = std::index_sequence_for; // generates size_t: 0,1 + using intmix = std::integer_sequence; // generates int: 9,8,7,2 + using sizemix = std::index_sequence<1, 1, 2, 3, 5>; // generates size_t: 1,1,2,3,5 + + // Make sure they're what we expect + static_assert ( std::is_same ::value, "int3 type wrong" ); + static_assert ( int3::static_size == 3, "int3 size wrong" ); + + static_assert ( std::is_same ::value, "size7 type wrong" ); + static_assert ( size7::static_size == 7, "size7 size wrong" ); + + static_assert ( std::is_same ::value, "size4 type wrong" ); + static_assert ( size4::static_size == 4, "size4 size wrong" ); + + static_assert ( std::is_same ::value, "size2 type wrong" ); + static_assert ( size2::static_size == 2, "size2 size wrong" ); + + static_assert ( std::is_same ::value, "intmix type wrong" ); + static_assert ( intmix::static_size == 4, "intmix size wrong" ); + + static_assert ( std::is_same ::value, "sizemix type wrong" ); + static_assert ( sizemix::static_size == 5, "sizemix size wrong" ); + + auto tup = std::make_tuple ( 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ); + + // Use them + auto t3 = extract ( tup, int3() ); + static_assert ( std::tuple_size::value == int3::static_size, "t3 size wrong"); + expect ( t3 == std::make_tuple ( 10, 11, 12 )); + + auto t7 = extract ( tup, size7 ()); + static_assert ( std::tuple_size::value == size7::static_size, "t7 size wrong"); + expect ( t7 == std::make_tuple ( 10, 11, 12, 13, 14, 15, 16 )); + + auto t4 = extract ( tup, size4 ()); + static_assert ( std::tuple_size::value == size4::static_size, "t4 size wrong"); + expect ( t4 == std::make_tuple ( 10, 11, 12, 13 )); + + auto t2 = extract ( tup, size2 ()); + static_assert ( std::tuple_size::value == size2::static_size, "t2 size wrong"); + expect ( t2 == std::make_tuple ( 10, 11 )); + + auto tintmix = extract ( tup, intmix ()); + static_assert ( std::tuple_size::value == intmix::static_size, "tintmix size wrong"); + expect ( tintmix == std::make_tuple ( 19, 18, 17, 12 )); + + auto tsizemix = extract ( tup, sizemix ()); + static_assert ( std::tuple_size::value == sizemix::static_size, "tsizemix size wrong"); + expect ( tsizemix == std::make_tuple ( 11, 11, 12, 13, 15 )); + pass(); + } + + integer_sequence_Tests() : UnitTest ("integer_sequence", "beast") + { + } +}; + +static integer_sequence_Tests integer_sequence_tests; + +} +} diff --git a/beast/cxx14/utility.h b/beast/cxx14/utility.h new file mode 100644 index 000000000..80afe8d61 --- /dev/null +++ b/beast/cxx14/utility.h @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CXX14_UTILITY_H_INCLUDED +#define BEAST_CXX14_UTILITY_H_INCLUDED + +#include "config.h" + +#include +#include +#include + +namespace std { + +template +struct integer_sequence +{ + typedef T value_type; + static_assert (is_integral::value, + "std::integer_sequence can only be instantiated with an integral type" ); + + static const size_t static_size = sizeof...(Ints); + + static /* constexpr */ size_t size() /* noexcept */ + { + return sizeof...(Ints); + } +}; + +template +using index_sequence = integer_sequence ; + +namespace detail { + +// This workaround is needed for msvc broken sizeof... +template +struct sizeof_workaround +{ + static size_t const size = sizeof... (Args); +}; + +} // detail + +#ifdef _MSC_VER + +// This implementation compiles on MSVC and clang but not gcc + +namespace detail { + +template +struct make_integer_sequence_unchecked; + +template +struct make_integer_sequence_unchecked < + T, N, integer_sequence > +{ + typedef typename make_integer_sequence_unchecked< + T, N-1, integer_sequence>::type type; +}; + +template +struct make_integer_sequence_unchecked < + T, 0, integer_sequence> +{ + typedef integer_sequence type; +}; + +template +struct make_integer_sequence_checked +{ + static_assert (is_integral ::value, + "T must be an integral type"); + + static_assert (N >= 0, + "N must be non-negative"); + + typedef typename make_integer_sequence_unchecked < + T, N, integer_sequence>::type type; +}; + +} // detail + +template +using make_integer_sequence = + typename detail::make_integer_sequence_checked ::type; + +template +using make_index_sequence = make_integer_sequence ; + +template +using index_sequence_for = + make_index_sequence ::size>; + +#else + +// This implementation compiles on gcc but not MSVC + +namespace detail { + +template +struct index_tuple +{ + typedef index_tuple next; + +}; + +template +struct build_index_tuple +{ + typedef typename build_index_tuple ::type::next type; +}; + +template <> +struct build_index_tuple <0> +{ + typedef index_tuple<> type; +}; + +template ::type +> +struct make_integer_sequence; + +template +struct make_integer_sequence > +{ + static_assert (is_integral ::value, + "T must be an integral type"); + + static_assert (N >= 0, + "N must be non-negative"); + + typedef integer_sequence (Ints)...> type; +}; + +} // detail + +template +using make_integer_sequence = + typename detail::make_integer_sequence ::type; + +template +using make_index_sequence = make_integer_sequence ; + +template +using index_sequence_for = + make_index_sequence ::size>; + +#endif + +} + +#endif