-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add std::integer_sequence C++14 compatibility
- Loading branch information
1 parent
4e35760
commit e3c1375
Showing
5 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//------------------------------------------------------------------------------ | ||
/* | ||
This file is part of Beast: https://github.com/vinniefalco/Beast | ||
Copyright 2013, Vinnie Falco <[email protected]> | ||
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
//------------------------------------------------------------------------------ | ||
/* | ||
This file is part of Beast: https://github.com/vinniefalco/Beast | ||
Copyright 2013, Vinnie Falco <[email protected]> | ||
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 <class AtContainer, class T, T... I> | ||
static | ||
auto | ||
extract (AtContainer const& t, | ||
std::integer_sequence <T, I...>) -> | ||
decltype (std::make_tuple (std::get <I> (t)...)) | ||
{ | ||
return std::make_tuple (std::get <I> (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<int, 3>; // generates int: 0,1,2 | ||
using size7 = std::make_integer_sequence<size_t, 7>; // 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<int, size_t>; // generates size_t: 0,1 | ||
using intmix = std::integer_sequence<int, 9, 8, 7, 2>; // 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 <int3::value_type, int>::value, "int3 type wrong" ); | ||
static_assert ( int3::static_size == 3, "int3 size wrong" ); | ||
|
||
static_assert ( std::is_same <size7::value_type, size_t>::value, "size7 type wrong" ); | ||
static_assert ( size7::static_size == 7, "size7 size wrong" ); | ||
|
||
static_assert ( std::is_same <size4::value_type, size_t>::value, "size4 type wrong" ); | ||
static_assert ( size4::static_size == 4, "size4 size wrong" ); | ||
|
||
static_assert ( std::is_same <size2::value_type, size_t>::value, "size2 type wrong" ); | ||
static_assert ( size2::static_size == 2, "size2 size wrong" ); | ||
|
||
static_assert ( std::is_same <intmix::value_type, int>::value, "intmix type wrong" ); | ||
static_assert ( intmix::static_size == 4, "intmix size wrong" ); | ||
|
||
static_assert ( std::is_same <sizemix::value_type, size_t>::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<decltype(t3)>::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<decltype(t7)>::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<decltype(t4)>::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<decltype(t2)>::value == size2::static_size, "t2 size wrong"); | ||
expect ( t2 == std::make_tuple ( 10, 11 )); | ||
|
||
auto tintmix = extract ( tup, intmix ()); | ||
static_assert ( std::tuple_size<decltype(tintmix)>::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<decltype(tsizemix)>::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; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
//------------------------------------------------------------------------------ | ||
/* | ||
This file is part of Beast: https://github.com/vinniefalco/Beast | ||
Copyright 2013, Vinnie Falco <[email protected]> | ||
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 <cstddef> | ||
#include <type_traits> | ||
#include <utility> | ||
|
||
namespace std { | ||
|
||
template <class T, T... Ints> | ||
struct integer_sequence | ||
{ | ||
typedef T value_type; | ||
static_assert (is_integral<T>::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 <size_t... Ints> | ||
using index_sequence = integer_sequence <size_t, Ints...>; | ||
|
||
namespace detail { | ||
|
||
// This workaround is needed for msvc broken sizeof... | ||
template <class... Args> | ||
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 <class T, unsigned long long N, class Seq> | ||
struct make_integer_sequence_unchecked; | ||
|
||
template <class T, unsigned long long N, unsigned long long ...Indices> | ||
struct make_integer_sequence_unchecked < | ||
T, N, integer_sequence <T, Indices...>> | ||
{ | ||
typedef typename make_integer_sequence_unchecked< | ||
T, N-1, integer_sequence<T, N-1, Indices...>>::type type; | ||
}; | ||
|
||
template <class T, unsigned long long ...Indices> | ||
struct make_integer_sequence_unchecked < | ||
T, 0, integer_sequence<T, Indices...>> | ||
{ | ||
typedef integer_sequence <T, Indices...> type; | ||
}; | ||
|
||
template <class T, T N> | ||
struct make_integer_sequence_checked | ||
{ | ||
static_assert (is_integral <T>::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<T>>::type type; | ||
}; | ||
|
||
} // detail | ||
|
||
template <class T, T N> | ||
using make_integer_sequence = | ||
typename detail::make_integer_sequence_checked <T, N>::type; | ||
|
||
template <size_t N> | ||
using make_index_sequence = make_integer_sequence <size_t, N>; | ||
|
||
template <class... Args> | ||
using index_sequence_for = | ||
make_index_sequence <detail::sizeof_workaround <Args...>::size>; | ||
|
||
#else | ||
|
||
// This implementation compiles on gcc but not MSVC | ||
|
||
namespace detail { | ||
|
||
template <size_t... Ints> | ||
struct index_tuple | ||
{ | ||
typedef index_tuple <Ints..., sizeof... (Ints)> next; | ||
|
||
}; | ||
|
||
template <size_t N> | ||
struct build_index_tuple | ||
{ | ||
typedef typename build_index_tuple <N-1>::type::next type; | ||
}; | ||
|
||
template <> | ||
struct build_index_tuple <0> | ||
{ | ||
typedef index_tuple<> type; | ||
}; | ||
|
||
template <class T, T N, | ||
class Seq = typename build_index_tuple <N>::type | ||
> | ||
struct make_integer_sequence; | ||
|
||
template <class T, T N, size_t... Ints> | ||
struct make_integer_sequence <T, N, index_tuple <Ints...>> | ||
{ | ||
static_assert (is_integral <T>::value, | ||
"T must be an integral type"); | ||
|
||
static_assert (N >= 0, | ||
"N must be non-negative"); | ||
|
||
typedef integer_sequence <T, static_cast <T> (Ints)...> type; | ||
}; | ||
|
||
} // detail | ||
|
||
template <class T, T N> | ||
using make_integer_sequence = | ||
typename detail::make_integer_sequence <T, N>::type; | ||
|
||
template <size_t N> | ||
using make_index_sequence = make_integer_sequence <size_t, N>; | ||
|
||
template <class... Args> | ||
using index_sequence_for = | ||
make_index_sequence <detail::sizeof_workaround <Args...>::size>; | ||
|
||
#endif | ||
|
||
} | ||
|
||
#endif |