summaryrefslogtreecommitdiff
path: root/sigc++
diff options
context:
space:
mode:
authorMurray Cumming <murrayc@murrayc.com>2018-04-15 23:06:27 +0200
committerMurray Cumming <murrayc@murrayc.com>2018-04-15 23:06:37 +0200
commit5a95388651619b2a1399c2920d1fd1c09d513576 (patch)
tree14b4a0fa8b28f7cbb7c1acadd6d19188a4e8e0f2 /sigc++
parent1759faf552248373714acc573b55421e86cb94cc (diff)
downloadsigc++-5a95388651619b2a1399c2920d1fd1c09d513576.tar.gz
C++17: Update tuple_transform_each().
Update from murrayc-tuple-utils: https://github.com/murraycu/murrayc-tuple-utils/commits/master
Diffstat (limited to 'sigc++')
-rw-r--r--sigc++/tuple-utils/tuple_transform_each.h131
1 files changed, 49 insertions, 82 deletions
diff --git a/sigc++/tuple-utils/tuple_transform_each.h b/sigc++/tuple-utils/tuple_transform_each.h
index ff7b6a4..7649e7f 100644
--- a/sigc++/tuple-utils/tuple_transform_each.h
+++ b/sigc++/tuple-utils/tuple_transform_each.h
@@ -18,88 +18,57 @@
#ifndef SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H
#define SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H
+// #include <sigc++/tuple-utils/tuple_cat.h>
#include <sigc++/tuple-utils/tuple_cdr.h>
#include <sigc++/tuple-utils/tuple_end.h>
#include <sigc++/tuple-utils/tuple_start.h>
#include <type_traits>
-namespace sigc
-{
+namespace sigc::internal {
-namespace internal
-{
-
-namespace detail
-{
+namespace detail {
template <template <typename> class T_transformer, std::size_t size_from_index>
-struct tuple_transform_each_impl
-{
+struct tuple_transform_each_impl {
// TODO: Avoid the need to pass t_original all the way into the recursion?
template <typename T_current, typename T_original>
- constexpr static decltype(auto) tuple_transform_each(T_current&& t, T_original& t_original)
- {
- // We use std::decay_t<> because tuple_size is not defined for references.
- constexpr auto size = std::tuple_size<std::decay_t<T_current>>::value;
- static_assert(size > 1, "size must be more than 0.");
-
- constexpr auto index = size - size_from_index;
- static_assert(index >= 0, "unexpected index.");
-
- using from_element_type = typename std::tuple_element<index, std::decay_t<T_original>>::type;
- using to_element_type = typename std::result_of<decltype (
- &T_transformer<from_element_type>::transform)(from_element_type&)>::type;
- const auto t_element = std::tuple<to_element_type>(
- T_transformer<from_element_type>::transform(std::get<index>(t_original)));
-
- const auto t_start = tuple_start<index>(std::forward<T_current>(t));
-
- // t_end's elements will be copies of the elements in t, so this method's
- // caller won't see the changes made in the subsequent call of
- // tuple_transform_each() on those copies. That's why we pass t_original
- // through too, so we can modify that directly.
- // the const version (tuple_transform_each_const()) doesn't have to worry
- // about this, though avoiding copying would be more efficient.
- const auto t_end = tuple_end<size - index - 1>(t);
-
- auto t_with_transformed_element = std::tuple_cat(t_start, t_element, t_end);
- return tuple_transform_each_impl<T_transformer, size_from_index - 1>::tuple_transform_each(
- t_with_transformed_element, t_original);
- }
-};
-
-template <template <typename> class T_transformer>
-struct tuple_transform_each_impl<T_transformer, 1>
-{
- template <typename T_current, typename T_original>
- constexpr static decltype(auto) tuple_transform_each(T_current&& t, T_original& t_original)
- {
- // We use std::decay_t<> because tuple_size is not defined for references.
- constexpr auto size = std::tuple_size<std::decay_t<T_current>>::value;
- static_assert(size > 0, "size must be more than 0.");
-
- constexpr auto index = size - 1;
- static_assert(index >= 0, "unexpected index.");
-
- using from_element_type = typename std::tuple_element<index, T_original>::type;
- using to_element_type = typename std::result_of<decltype (
- &T_transformer<from_element_type>::transform)(from_element_type&)>::type;
- const auto tuple_element = std::tuple<to_element_type>(
- T_transformer<from_element_type>::transform(std::get<index>(t_original)));
-
- const auto tuple_rest = tuple_start<size - 1>(std::forward<T_current>(t));
- return std::tuple_cat(tuple_rest, tuple_element);
- }
-};
-
-template <template <typename> class T_transformer>
-struct tuple_transform_each_impl<T_transformer, 0>
-{
- template <typename T_current, typename T_original>
- constexpr static decltype(auto) tuple_transform_each(T_current&& t, T_original& /* t_original */)
- {
- // Do nothing because the tuple has no elements.
- return std::forward<T_current>(t);
+ constexpr
+ static decltype(auto)
+ tuple_transform_each(T_current&& t, T_original& t_original) {
+ if constexpr(size_from_index == 0) {
+ //Do nothing because the tuple has no elements.
+ return std::forward<T_current>(t);
+ } else { //TODO: Should this compile without using else to contain the alternative code?
+ //We use std::decay_t<> because tuple_size is not defined for references.
+ constexpr auto size = std::tuple_size<std::decay_t<T_current>>::value;
+ constexpr auto index = size - size_from_index;
+ static_assert(index >= 0, "unexpected index.");
+
+ using from_element_type = typename std::tuple_element<index, std::decay_t<T_original>>::type;
+ using to_element_type = typename std::result_of<decltype (
+ &T_transformer<from_element_type>::transform)(from_element_type&)>::type;
+ const auto t_element =
+ std::tuple<to_element_type>(T_transformer<from_element_type>::transform(std::get<index>(t_original)));
+
+ if constexpr(size_from_index == 1) {
+ const auto tuple_rest = tuple_start<size - 1>(std::forward<T_current>(t));
+ return std::tuple_cat(tuple_rest, t_element);
+ } else {
+ const auto t_start = tuple_start<index>(std::forward<T_current>(t));
+
+ // t_end's elements will be copies of the elements in t, so this method's
+ // caller won't see the changes made in the subsequent call of
+ // tuple_transform_each() on those copies. That's why we pass t_original
+ // through too, so we can modify that directly.
+ // the const version (tuple_transform_each_const()) doesn't have to worry
+ // about this, though avoiding copying would be more efficient.
+ const auto t_end = tuple_end<size - index - 1>(t);
+
+ auto t_with_transformed_element = std::tuple_cat(t_start, t_element, t_end);
+ return tuple_transform_each_impl<T_transformer,
+ size_from_index - 1>::tuple_transform_each(t_with_transformed_element, t_original);
+ }
+ }
}
};
@@ -110,18 +79,16 @@ struct tuple_transform_each_impl<T_transformer, 0>
* in the original tuple.
*/
template <template <typename> class T_transformer, typename T>
-constexpr decltype(auto)
-tuple_transform_each(T&& t)
-{
- // We use std::decay_t<> because tuple_size is not defined for references.
+constexpr
+decltype(auto)
+tuple_transform_each(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;
- return detail::tuple_transform_each_impl<T_transformer, size>::tuple_transform_each(
- std::forward<T>(t), t);
+ return detail::tuple_transform_each_impl<T_transformer,
+ size>::tuple_transform_each(std::forward<T>(t), t);
}
-} // namespace internal
-
-} // namespace sigc
+} // namespace sigc::internal
-#endif // SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H
+#endif //SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H