Skip to content

Commit

Permalink
Add std::integer_sequence C++14 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
vinniefalco committed Mar 14, 2014
1 parent 4e35760 commit e3c1375
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/beast/Builds/VisualStudio2013/beast.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
<ClInclude Include="..\..\beast\cxx14\functional.h" />
<ClInclude Include="..\..\beast\cxx14\memory.h" />
<ClInclude Include="..\..\beast\cxx14\type_traits.h" />
<ClInclude Include="..\..\beast\cxx14\utility.h" />
<ClInclude Include="..\..\beast\cyclic_iterator.h" />
<ClInclude Include="..\..\beast\FixedArray.h" />
<ClInclude Include="..\..\beast\HeapBlock.h" />
Expand Down Expand Up @@ -518,6 +519,13 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\cxx14\cxx14.cpp" />
<ClCompile Include="..\..\beast\cxx14\tests\integer_sequence.test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\http\HTTP.cpp" />
<ClCompile Include="..\..\beast\http\impl\http_parser.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
Expand Down
12 changes: 12 additions & 0 deletions src/beast/Builds/VisualStudio2013/beast.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@
<Filter Include="beast\container\tests">
<UniqueIdentifier>{4b468051-9e97-4548-a5f0-469425c3b603}</UniqueIdentifier>
</Filter>
<Filter Include="beast\cxx14\tests">
<UniqueIdentifier>{1271ee71-5754-46ef-845b-84e53eed11c0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
Expand Down Expand Up @@ -1332,6 +1335,9 @@
<ClInclude Include="..\..\beast\container\buffer_view.h">
<Filter>beast\container</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\cxx14\utility.h">
<Filter>beast\cxx14</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_core\containers\DynamicObject.cpp">
Expand Down Expand Up @@ -1919,6 +1925,12 @@
<ClCompile Include="..\..\beast\container\tests\buffer_view.test.cpp">
<Filter>beast\container\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\cxx14\cxx14.cpp">
<Filter>beast\cxx14</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\cxx14\tests\integer_sequence.test.cpp">
<Filter>beast\cxx14\tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt">
Expand Down
20 changes: 20 additions & 0 deletions src/beast/beast/cxx14/cxx14.cpp
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"
113 changes: 113 additions & 0 deletions src/beast/beast/cxx14/tests/integer_sequence.test.cpp
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;

}
}
169 changes: 169 additions & 0 deletions src/beast/beast/cxx14/utility.h
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

0 comments on commit e3c1375

Please sign in to comment.