Permalink
Browse files

C++17: Update from murrayc-tuple-utils.

From https://github.com/murraycu/murrayc-tuple-utils/commits/master
This also uses the C++17 nested namespace syntax.

Apart from tuple_transform_each, which seems to have a memory access
problem, with both g++ and clang++, in its C++17 version.
  • Loading branch information...
murraycu committed Apr 15, 2018
1 parent 12ad173 commit 1759faf552248373714acc573b55421e86cb94cc
Showing with 60 additions and 78 deletions.
  1. +10 −16 sigc++/tuple-utils/tuple_cdr.h
  2. +33 −36 sigc++/tuple-utils/tuple_end.h
  3. +17 −26 sigc++/tuple-utils/tuple_start.h
@@ -22,11 +22,7 @@
#include <type_traits>
#include <utility>
namespace sigc
{
namespace internal
{
namespace sigc::internal {
/**
* Get the type of a tuple without the first item.
@@ -41,11 +37,11 @@ struct tuple_type_cdr<std::tuple<H, T...>>
using type = std::tuple<T...>;
};
namespace detail
{
namespace detail {
template <typename T, std::size_t... I>
constexpr decltype(auto)
constexpr
decltype(auto)
tuple_cdr_impl(T&& t, std::index_sequence<0, I...>)
{
using cdr = typename tuple_type_cdr<std::decay_t<T>>::type;
@@ -59,19 +55,17 @@ tuple_cdr_impl(T&& t, std::index_sequence<0, I...>)
* This is analogous to std::tuple_cat().
*/
template <typename T>
constexpr decltype(auto)
tuple_cdr(T&& t)
{
// We use std::decay_t<> because tuple_size is not defined for references.
constexpr
decltype(auto)
tuple_cdr(T&& t) {
//We use std::decay_t<> because tuple_size is not defined for references.
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
static_assert(size != 0, "tuple size must be non-zero");
using seq = std::make_index_sequence<size>;
return detail::tuple_cdr_impl(std::forward<T>(t), seq{});
}
} // namespace internal
} // namespace sigc
} // namespace sigc::internal
#endif // SIGC_TUPLE_UTILS_TUPLE_CDR_H
#endif //SIGC_TUPLE_UTILS_TUPLE_CDR_H
@@ -20,58 +20,55 @@
#include <sigc++/tuple-utils/tuple_cdr.h>
namespace sigc
{
namespace sigc::internal {
namespace internal
{
namespace detail
{
namespace detail {
template <typename T, std::size_t remove_from_start>
struct tuple_end_impl
{
constexpr static decltype(auto) // typename tuple_type_end<T, size - remove_from_start>::type
tuple_end(T&& t)
{
static_assert(remove_from_start > 0, "remove_from_start must be more than zero.");
using cdr = typename tuple_type_cdr<std::decay_t<T>>::type;
return tuple_end_impl<cdr, remove_from_start - 1>::tuple_end(tuple_cdr(std::forward<T>(t)));
}
};
template <typename T>
struct tuple_end_impl<T, 1>
{
constexpr static decltype(auto) tuple_end(T&& t) { return tuple_cdr(std::forward<T>(t)); }
struct tuple_type_end_impl {
using type = typename tuple_type_end_impl<typename tuple_type_cdr<std::decay_t<T>>::type,
remove_from_start - 1>::type;
};
template <typename T>
struct tuple_end_impl<T, 0>
{
constexpr static decltype(auto) tuple_end(T&& t) { return std::forward<T>(t); }
struct tuple_type_end_impl<T, 0> {
using type = T;
};
} // detail namespace
/**
* Get the type of a tuple with the last @a len types of the original.
*/
template <typename T, std::size_t len>
struct tuple_type_end
: detail::tuple_type_end_impl<T, std::tuple_size<T>::value - len> {};
/**
* Get the tuple with the last @a len items of the original.
*/
template <std::size_t len, typename T>
constexpr decltype(auto) // typename tuple_type_end<T, len>::type
tuple_end(T&& t)
{
// We use std::decay_t<> because tuple_size is not defined for references.
constexpr
decltype(auto) // typename tuple_type_end<T, len>::type
tuple_end(T&& t) {
//We use std::decay_t<> because tuple_size is not defined for references.
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
static_assert(len <= size, "The tuple size must be less than or equal to the length.");
constexpr auto size_start = size - len;
return detail::tuple_end_impl<T, size_start>::tuple_end(std::forward<T>(t));
}
} // namespace internal
if constexpr(len == 0) {
// Recursive calls to tuple_cdr() would result in this eventually,
// but this avoids the extra work:
return std::tuple<>();
} else if constexpr(size - len == 0) {
return std::forward<T>(t);
} else if constexpr(size - len == 1) {
return tuple_cdr(std::forward<T>(t));
} else {
return tuple_end<len>(
tuple_cdr(std::forward<T>(t)));
}
}
} // namespace sigc
} // namespace sigc::internal;
#endif // SIGC_TUPLE_UTILS_TUPLE_END_H
#endif //SIGC_TUPLE_UTILS_TUPLE_END_H
@@ -21,21 +21,15 @@
#include <tuple>
#include <utility>
namespace sigc
{
namespace sigc::internal {
namespace internal
{
namespace detail
{
namespace detail {
template <typename T, typename Seq>
struct tuple_type_start_impl;
template <typename T, std::size_t... I>
struct tuple_type_start_impl<T, std::index_sequence<I...>>
{
struct tuple_type_start_impl<T, std::index_sequence<I...>> {
using type = std::tuple<typename std::tuple_element<I, T>::type...>;
};
@@ -45,21 +39,20 @@ struct tuple_type_start_impl<T, std::index_sequence<I...>>
* Get the type of a tuple with just the first @len items.
*/
template <typename T, std::size_t len>
struct tuple_type_start : detail::tuple_type_start_impl<T, std::make_index_sequence<len>>
{
};
struct tuple_type_start
: detail::tuple_type_start_impl<T, std::make_index_sequence<len>> {};
namespace detail
{
namespace detail {
template <typename T, typename Seq>
struct tuple_start_impl;
template <typename T, std::size_t... I>
struct tuple_start_impl<T, std::index_sequence<I...>>
{
static constexpr decltype(auto) tuple_start(T&& t)
{
struct tuple_start_impl<T, std::index_sequence<I...>> {
static
constexpr
decltype(auto)
tuple_start(T&& t) {
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
constexpr auto len = sizeof...(I);
static_assert(len <= size, "The tuple size must be less than or equal to the length.");
@@ -75,19 +68,17 @@ struct tuple_start_impl<T, std::index_sequence<I...>>
* Get the tuple with the last @a len items of the original.
*/
template <std::size_t len, typename T>
constexpr decltype(auto) // typename tuple_type_end<T, len>::type
tuple_start(T&& t)
{
// We use std::decay_t<> because tuple_size is not defined for references.
constexpr
decltype(auto) // typename tuple_type_end<T, len>::type
tuple_start(T&& t) {
//We use std::decay_t<> because tuple_size is not defined for references.
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
static_assert(len <= size, "The tuple size must be less than or equal to the length.");
return detail::tuple_start_impl<T, std::make_index_sequence<len>>::tuple_start(
std::forward<T>(t));
}
} // namespace internal
} // namespace sigc
} // namespace sigc::internal;
#endif // SIGC_TUPLE_UTILS_TUPLE_START_H
#endif //SIGC_TUPLE_UTILS_TUPLE_START_H

0 comments on commit 1759faf

Please sign in to comment.