[libsigc++2/variadic] hide.h.m4: hide_functor::operator(): Make this variadic.



commit fa8ea8f662e80c27cc146c872e5f434b1416abca
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Jan 14 17:22:19 2016 +0100

    hide.h.m4: hide_functor::operator(): Make this variadic.
    
    This uses some tuple manipulation utilities so that the variadic parameters
    with which we call a method can be based on the variadic parameters that the
    caller received, but not exactly. In this case, we need to replace an element
    in the middle of a tuple. There is probably a more efficient way to do this.
    
    For now, this is using copies of the tuple utilities from here:
    https://github.com/murraycu/murrayc-tuple-utils/tree/master/tuple-utils

 sigc++/adaptors/macros/hide.h.m4 |   88 +++++++++++++++++---------------
 sigc++/filelist.am               |    4 ++
 sigc++/tuple_cat.h               |   59 +++++++++++++++++++++
 sigc++/tuple_cdr.h               |   56 ++++++++++++++++++++
 sigc++/tuple_end.h               |   71 ++++++++++++++++++++++++++
 sigc++/tuple_start.h             |   60 ++++++++++++++++++++++
 tests/.gitignore                 |    4 ++
 tests/Makefile.am                |    8 +++
 tests/test_tuple_cat.cc          |   39 ++++++++++++++
 tests/test_tuple_cdr.cc          |   38 ++++++++++++++
 tests/test_tuple_end.cc          |  104 ++++++++++++++++++++++++++++++++++++++
 tests/test_tuple_start.cc        |   95 ++++++++++++++++++++++++++++++++++
 12 files changed, 585 insertions(+), 41 deletions(-)
---
diff --git a/sigc++/adaptors/macros/hide.h.m4 b/sigc++/adaptors/macros/hide.h.m4
index 0714c7a..b37cadc 100644
--- a/sigc++/adaptors/macros/hide.h.m4
+++ b/sigc++/adaptors/macros/hide.h.m4
@@ -22,46 +22,6 @@ define([ORDINAL],[dnl
 ifelse($1,0,,$1)ifelse($1,0,[last],$1,1,[st],$1,2,[nd],$1,3,[rd],[th])[]dnl
 ])
 
-define([HIDE_OPERATOR],[dnl
-ifelse($2,0,,[dnl
-ifelse($2,1,[dnl
-  /** Invokes the wrapped functor ignoring the only argument.
-   * @param _A_a1 Argument to be ignored.
-   * @return The return value of the functor invocation.
-   */
-  template <class T_arg1>
-  decltype(auto)
-  operator()(T_arg1)
-    { return this->functor_(); }
-
-],$1,0,[dnl
-  /** Invokes the wrapped functor, ignoring the last argument.dnl
-FOR(1, eval($2-1),[
-   * @param _A_a%1 Argument to be passed on to the functor.])
-   * @param _A_a$2 Argument to be ignored.
-   * @return The return value of the functor invocation.
-   */
-  template <LOOP([class T_arg%1], $2)>
-  decltype(auto)
-  operator()(LOOP(T_arg%1 _A_a%1, eval($2-1)), T_arg$2)
-    { return 
this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(FOR(1,eval($2-1),[type_trait_pass_t<T_arg%1>,]))>
-        (LIST(FOR(1,eval($2-1),[_A_a%1,]))); }
-
-],[dnl
-  /** Invokes the wrapped functor, ignoring the ORDINAL($1) argument.dnl
-FOR(1, eval($1-1),[
-   * @param _A_a%1 Argument to be passed on to the functor.])
-   * @param _A_a$1 Argument to be ignored.dnl
-FOR(eval($1+1), $2,[
-   * @param _A_a%1 Argument to be passed on to the functor.])
-   * @return The return value of the functor invocation.
-   */
-  template <LOOP([class T_arg%1], $2)>
-  decltype(auto)
-  operator()(LIST(FOR(1,eval($1-1),[T_arg%1 _A_a%1,]),T_arg$1,FOR(eval($1+1),$2,[T_arg%1 _A_a%1,])))
-    { return 
this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(FOR(1,eval($1-1),[type_trait_pass_t<T_arg%1>,]),FOR(eval($1+1),
 $2,[type_trait_pass_t<T_arg%1>,]))>
-        (LIST(FOR(1,eval($1-1),[_A_a%1,]),FOR(eval($1+1),$2,[_A_a%1,]))); }
-
 ])])dnl
 ])dnl end HIDE_OPERATOR
 
@@ -79,7 +39,39 @@ struct hide_functor <$1, T_functor> : public adapts<T_functor>
   typedef typename adapts<T_functor>::adaptor_type adaptor_type;
   typedef typename adaptor_type::result_type  result_type;
 
-FOR(eval($1+1),CALL_SIZE,[[HIDE_OPERATOR(eval($1+1),%1)]])dnl
+  /** Invokes the wrapped functor, ignoring the ORDINAL($1) argument.dnl
+   * @param _A_a Arguments to be passed on to the functor, apart from the ORDINAL($1) argument.
+   * @return The return value of the functor invocation.
+   */
+  template <class... T_arg>
+  decltype(auto)
+  operator()(T_arg... _A_a)
+    {
+       constexpr auto size = sizeof...(T_arg);
+       constexpr auto index_ignore = ($1 == -1 ? size - 1 : $1);
+       const auto t = std::make_tuple(_A_a...);
+
+       const auto t_start = tuple_start<index_ignore>(t);
+       const auto t_end = tuple_end<size - index_ignore - 1>(t);
+       auto t_used = std::tuple_cat(t_start, t_end); //TODO: Let this be const?
+
+       //This is so we can specify a particular instantiation of the functor's
+       //operator().
+       //TODO: Avoid this if it no longer necessary.
+       using t_type = std::tuple<type_trait_pass_t<T_arg>...>;
+       using t_type_start = typename tuple_type_start<t_type, index_ignore>::type;
+       using t_type_end = typename tuple_type_end<t_type, size - index_ignore - 1>::type;
+       using t_type_used = typename tuple_type_cat<t_type_start, t_type_end>::type;
+
+       constexpr auto size_used = size - 1;
+
+       //TODO: Remove these? They are just here as a sanity check.
+       static_assert(std::tuple_size<t_type_used>::value == size_used, "Unexpected t_type_used size.");
+       static_assert(std::tuple_size<decltype(t_used)>::value == size_used, "Unexpected t_used size.");
+
+       const auto seq = std::make_index_sequence<size_used>();
+       return call_functor_operator_parentheses<t_type_used>(t_used, seq);
+    }
 
   /** Constructs a hide_functor object that adds a dummy parameter to the passed functor.
    * @param _A_func Functor to invoke from operator()().
@@ -87,6 +79,17 @@ FOR(eval($1+1),CALL_SIZE,[[HIDE_OPERATOR(eval($1+1),%1)]])dnl
   explicit hide_functor(const T_functor& _A_func)
     : adapts<T_functor>(_A_func)
     {}
+
+private:
+  //TODO_variadic: Replace this with std::experimental::apply() if that becomes standard
+  //C++, or add our own implementation, to avoid code duplication.
+  template<class T_tuple_specific, class T_tuple, std::size_t... Is>
+  decltype(auto)
+  call_functor_operator_parentheses(T_tuple& tuple,
+    std::index_sequence<Is...>)
+  {
+    return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<typename std::tuple_element<Is, 
T_tuple_specific>::type...>(std::get<Is>(tuple)...);
+  }
 };
 ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS
 ],)dnl Include only the first two template specializations in the documentation. ($1 = -1..CALL_SIZE-1)
@@ -96,6 +99,9 @@ ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS
 divert(0)dnl
 _FIREWALL([ADAPTORS_HIDE])
 #include <sigc++/adaptors/adaptor_trait.h>
+#include <sigc++/tuple_cat.h>
+#include <sigc++/tuple_end.h>
+#include <sigc++/tuple_start.h>
 
 namespace sigc {
 
diff --git a/sigc++/filelist.am b/sigc++/filelist.am
index 0efa20e..d20005b 100644
--- a/sigc++/filelist.am
+++ b/sigc++/filelist.am
@@ -55,6 +55,10 @@ sigc_public_h =                              \
        signal_base.h                   \
        slot.h                  \
        trackable.h                     \
+       tuple_cat.h \
+       tuple_cdr.h \
+       tuple_end.h \
+       tuple_start.h \
        type_traits.h                   \
        visit_each.h                    \
        adaptors/adaptor_base.h \
diff --git a/sigc++/tuple_cat.h b/sigc++/tuple_cat.h
new file mode 100644
index 0000000..e96f722
--- /dev/null
+++ b/sigc++/tuple_cat.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2016 Murray Cumming
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/
+ */
+
+#ifndef _SIGC_TUPLE_UTILS_TUPLE_CAT_H_
+#define _SIGC_TUPLE_UTILS_TUPLE_CAT_H_
+
+#include <tuple>
+#include <utility>
+#include <type_traits>
+
+namespace sigc
+{
+
+namespace {
+
+template<typename T1, typename T2, typename Seq1, typename Seq2>
+struct tuple_type_cat_impl;
+
+template<typename T1, typename T2, std::size_t... I1, std::size_t... I2>
+struct tuple_type_cat_impl<T1, T2, std::index_sequence<I1...>, std::index_sequence<I2...>>
+{
+  using type = std::tuple<
+    typename std::tuple_element<I1, T1>::type...,
+    typename std::tuple_element<I2, T2>::type...>;
+};
+
+} //anonymous namespace
+
+/**
+ * Get the type of a tuple without the first item.
+ */
+template<typename T1, typename T2>
+struct tuple_type_cat
+: tuple_type_cat_impl<T1, T2,
+    std::make_index_sequence<std::tuple_size<T1>::value>,
+    std::make_index_sequence<std::tuple_size<T2>::value>>
+{};
+
+
+//There is no tuple_cat() here because std::tuple_cat() exists already in
+//the C++ standard library.
+
+
+} //namespace sigc
+
+#endif //_SIGC_TUPLE_UTILS_TUPLE_CAT_H_
diff --git a/sigc++/tuple_cdr.h b/sigc++/tuple_cdr.h
new file mode 100644
index 0000000..3d62d1f
--- /dev/null
+++ b/sigc++/tuple_cdr.h
@@ -0,0 +1,56 @@
+#ifndef _SIGC_TUPLE_CDR_H_
+#define _SIGC_TUPLE_CDR_H_
+
+#include <tuple>
+#include <utility>
+#include <type_traits>
+
+namespace sigc
+{
+
+namespace {
+
+template<typename T, typename Seq>
+struct tuple_type_cdr_impl;
+
+template<typename T, std::size_t I0, std::size_t... I>
+struct tuple_type_cdr_impl<T, std::index_sequence<I0, I...>>
+{
+  using type = std::tuple<typename std::tuple_element<I, T>::type...>;
+};
+
+} //anonymous namespace
+
+/**
+ * Get the type of a tuple without the first item.
+ */
+template<typename T>
+struct tuple_type_cdr
+: tuple_type_cdr_impl<T, std::make_index_sequence<std::tuple_size<T>::value>>
+{};
+
+
+namespace {
+
+template<typename T, std::size_t I0, std::size_t... I>
+decltype(auto) tuple_cdr_impl(const T& t, std::index_sequence<I0, I...>) {
+  return std::make_tuple(std::get<I>(t)...);
+}
+
+} //anonymous namespace
+
+/**
+ * Get the a tuple without the first item.
+ * This is analogous to std::tuple_cat().
+ */
+template<typename T>
+decltype(auto) tuple_cdr(const T& t) {
+  constexpr auto size = std::tuple_size<T>::value;
+  const auto seq = std::make_index_sequence<size>{};
+  return tuple_cdr_impl(t, seq);
+}
+
+
+} //namespace sigc
+
+#endif //_SIGC_TUPLE_CDR_H_
diff --git a/sigc++/tuple_end.h b/sigc++/tuple_end.h
new file mode 100644
index 0000000..6334f57
--- /dev/null
+++ b/sigc++/tuple_end.h
@@ -0,0 +1,71 @@
+#ifndef _SIGC_TUPLE_END_H_
+#define _SIGC_TUPLE_END_H_
+
+#include <sigc++/tuple_cdr.h>
+
+namespace sigc
+{
+
+namespace {
+
+template<typename T, std::size_t remove_from_start>
+struct tuple_type_end_impl
+{
+  using type = typename tuple_type_end_impl<typename tuple_type_cdr<T>::type, remove_from_start - 1>::type;
+};
+
+template<typename T>
+struct tuple_type_end_impl<T, 0>
+{
+  using type = T;
+};
+
+} //anonymous 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
+: tuple_type_end_impl<T, std::tuple_size<T>::value - len>
+{};
+
+
+namespace {
+
+template<typename T, std::size_t remove_from_start>
+struct tuple_end_impl
+{
+  static
+  decltype(auto) //typename tuple_type_end<T, size - remove_from_start>::type 
+  tuple_end(const T& t) {
+    return tuple_end_impl<typename tuple_type_cdr<T>::type, remove_from_start - 1>::tuple_end(tuple_cdr(t));
+  }
+};
+
+template<typename T>
+struct tuple_end_impl<T, 0>
+{
+  static
+  T
+  tuple_end(const T& t) {
+    return t;
+  }
+};
+
+} //anonymous namespace
+
+/**
+ * Get the ttuple with the last @a len items of the original.
+ */
+template<std::size_t len, typename T>
+decltype(auto) //typename tuple_type_end<T, len>::type 
+tuple_end(const T& t) {
+  constexpr auto size = std::tuple_size<T>::value; 
+  return tuple_end_impl<T, size - len>::tuple_end(t);
+}
+
+} //namespace sigc;
+
+#endif //_SIGC_TUPLE_END_H_
diff --git a/sigc++/tuple_start.h b/sigc++/tuple_start.h
new file mode 100644
index 0000000..487db65
--- /dev/null
+++ b/sigc++/tuple_start.h
@@ -0,0 +1,60 @@
+#ifndef _SIGC_TUPLE_START_H_
+#define _SIGC_TUPLE_START_H_
+
+#include <tuple>
+#include <utility>
+
+namespace sigc
+{
+
+namespace {
+
+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...>>
+{
+  using type = std::tuple<typename std::tuple_element<I, T>::type...>;
+};
+
+} //anonymous namespace
+
+/**
+ * Get the type of a tuple with just the first @len items.
+ */
+template<typename T, std::size_t len>
+struct tuple_type_start
+: tuple_type_start_impl<T, std::make_index_sequence<len>>
+{};
+
+
+namespace {
+
+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
+  decltype(auto)
+  tuple_start(const T& t) {
+    return std::make_tuple(std::get<I>(t)...);
+  }
+};
+
+} //anonymous namespace
+
+/**
+ * Get the tuple with the last @a len items of the original.
+ */
+template<std::size_t len, typename T>
+decltype(auto) //typename tuple_type_end<T, len>::type 
+tuple_start(const T& t) {
+  return tuple_start_impl<T, std::make_index_sequence<len>>::tuple_start(t);
+}
+
+} //namespace sigc;
+
+#endif //_SIGC_TUPLE_START_H_
diff --git a/tests/.gitignore b/tests/.gitignore
index be803fc..ff35316 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -30,4 +30,8 @@
 /test_trackable
 /test_trackable_move
 /test_track_obj
+/test_tuple_cat
+/test_tuple_cdr
+/test_tuple_end
+/test_tuple_start
 /test_visit_each
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fc58d03..1061ca8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -49,6 +49,10 @@ check_PROGRAMS = \
   test_trackable \
   test_trackable_move \
   test_track_obj \
+  test_tuple_cat \
+  test_tuple_cdr \
+  test_tuple_end \
+  test_tuple_start \
   test_visit_each
 
 TESTS = $(check_PROGRAMS)
@@ -84,4 +88,8 @@ test_slot_move_SOURCES       = test_slot_move.cc $(sigc_test_util)
 test_trackable_SOURCES       = test_trackable.cc $(sigc_test_util)
 test_trackable_move_SOURCES  = test_trackable_move.cc $(sigc_test_util)
 test_track_obj_SOURCES       = test_track_obj.cc $(sigc_test_util)
+test_tuple_cat_SOURCES       = test_tuple_cat.cc $(sigc_test_util)
+test_tuple_cdr_SOURCES       = test_tuple_cdr.cc $(sigc_test_util)
+test_tuple_end_SOURCES       = test_tuple_end.cc $(sigc_test_util)
+test_tuple_start_SOURCES     = test_tuple_start.cc $(sigc_test_util)
 test_visit_each_SOURCES      = test_visit_each.cc $(sigc_test_util)
diff --git a/tests/test_tuple_cat.cc b/tests/test_tuple_cat.cc
new file mode 100644
index 0000000..2300441
--- /dev/null
+++ b/tests/test_tuple_cat.cc
@@ -0,0 +1,39 @@
+/* Copyright (C) 2016 Murray Cumming
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/
+ */
+
+#include <sigc++/tuple_cat.h>
+#include <utility>
+#include <cstdlib>
+#include <cassert>
+
+void test_tuple_type_cat() {
+  using type_tuple_is = std::tuple<int, short>;
+  using type_tuple_dc = std::tuple<double, char>;
+  using type_tuple_cat = sigc::tuple_type_cat<type_tuple_is, type_tuple_dc>::type;
+  using type_tuple_expected = std::tuple<int, short, double, char>;
+
+  static_assert(std::tuple_size<type_tuple_cat>::value == 4,
+    "unexpected tuple_cat()ed tuple size.");
+  static_assert(std::is_same<type_tuple_cat, type_tuple_expected>::value,
+    "unexpected tuple_cat()ed tuple type");
+}
+
+int main() {
+  test_tuple_type_cat();
+  //There is no typeutils::tuple_cat() because std::tuple_cat() exists: test_tuple_cat();
+
+  return EXIT_SUCCESS;
+}
diff --git a/tests/test_tuple_cdr.cc b/tests/test_tuple_cdr.cc
new file mode 100644
index 0000000..387155a
--- /dev/null
+++ b/tests/test_tuple_cdr.cc
@@ -0,0 +1,38 @@
+#include <sigc++/tuple_cdr.h>
+#include <utility>
+#include <cstdlib>
+#include <cassert>
+
+
+void test_tuple_type_cdr() {
+  using type_tuple_isd = std::tuple<int, short, double>;
+  using type_tuple_sd = std::tuple<short, double>;
+  using type_tuple_suffix = sigc::tuple_type_cdr<type_tuple_isd>::type;
+
+  static_assert(std::tuple_size<type_tuple_suffix>::value == 2,
+    "unexpected tuple_cdr()ed tuple size.");
+  static_assert(std::is_same<type_tuple_suffix, type_tuple_sd>::value,
+    "unexpected tuple_cdr()ed tuple type");
+}
+
+void test_tuple_cdr() {
+  auto t_larger = std::make_tuple(nullptr, std::string("hello"),
+    std::string("world"));
+  auto t_suffix = sigc::tuple_cdr(t_larger);
+  assert(std::get<0>(t_suffix) == "hello");
+  assert(std::get<1>(t_suffix) == "world");
+
+  using type_tuple_suffix = std::tuple<std::string, std::string>;
+
+  static_assert(std::tuple_size<decltype(t_suffix)>::value == 2,
+    "unexpected cdr()ed tuple size.");
+  static_assert(std::is_same<decltype(t_suffix), type_tuple_suffix>::value,
+    "unexpected cdr()ed tuple type");
+}
+
+int main() {
+  test_tuple_type_cdr();
+  test_tuple_cdr();
+
+  return EXIT_SUCCESS;
+}
diff --git a/tests/test_tuple_end.cc b/tests/test_tuple_end.cc
new file mode 100644
index 0000000..411131d
--- /dev/null
+++ b/tests/test_tuple_end.cc
@@ -0,0 +1,104 @@
+// -*- c++ -*-
+/* Copyright 2016, The libsigc++ Development Team
+ *  Assigned to public domain.  Use as you wish without restriction.
+ */
+
+
+#include <sigc++/tuple_end.h>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+
+void test_tuple_type_end()
+{
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_end = sigc::tuple_type_end<type_tuple, 1>::type;
+    using type_tuple_expected = std::tuple<double>;
+
+    static_assert(std::tuple_size<type_tuple_end>::value == 1,
+      "unexpected tuple_end()ed tuple size.");
+    static_assert(std::is_same<type_tuple_end, type_tuple_expected>::value,
+      "unexpected type_tuple_end type");
+  }
+
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_end = sigc::tuple_type_end<type_tuple, 2>::type;
+    using type_tuple_expected = std::tuple<short, double>;
+
+    static_assert(std::tuple_size<type_tuple_end>::value == 2,
+      "unexpected tuple_end()ed tuple size.");
+    static_assert(std::is_same<type_tuple_end, type_tuple_expected>::value,
+      "unexpected type_tuple_end type");
+  }
+
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_end = sigc::tuple_type_end<type_tuple, 3>::type;
+    using type_tuple_expected = std::tuple<int, short, double>;
+
+    static_assert(std::tuple_size<type_tuple_end>::value == 3,
+      "unexpected tuple_end()ed tuple size.");
+    static_assert(std::is_same<type_tuple_end, type_tuple_expected>::value,
+        "unexpected type_tuple_end type");
+  }
+}
+
+void test_tuple_end()
+{
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_suffix = sigc::tuple_end<3>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_suffix)>::value == 3,
+      "unexpected tuple_end()ed tuple size.");
+
+    assert(std::get<0>(t_suffix) == nullptr);
+    assert(std::get<1>(t_suffix) == "hello");
+    assert(std::get<2>(t_suffix) == "world");
+
+    static_assert(std::is_same<decltype(t_suffix), decltype(t_original)>::value,
+      "unexpected end()ed tuple type");
+  }
+
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_suffix = sigc::tuple_end<2>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_suffix)>::value == 2,
+      "unexpected tuple_end()ed tuple size.");
+      
+    assert(std::get<0>(t_suffix) == "hello");
+    assert(std::get<1>(t_suffix) == "world");
+
+    using type_tuple_suffix = std::tuple<std::string, std::string>;
+    static_assert(std::is_same<decltype(t_suffix), type_tuple_suffix>::value,
+      "unexpected end()ed tuple type");
+  }
+
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_suffix = sigc::tuple_end<1>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_suffix)>::value == 1,
+      "unexpected tuple_end()ed tuple size.");
+
+    assert(std::get<0>(t_suffix) == "world");
+
+    using type_tuple_suffix = std::tuple<std::string>;
+    static_assert(std::is_same<decltype(t_suffix), type_tuple_suffix>::value,
+      "unexpected end()ed tuple type");
+  }
+}
+
+int main()
+{
+  test_tuple_type_end();
+  test_tuple_end();
+      
+  return EXIT_SUCCESS;
+}
diff --git a/tests/test_tuple_start.cc b/tests/test_tuple_start.cc
new file mode 100644
index 0000000..d7c16ed
--- /dev/null
+++ b/tests/test_tuple_start.cc
@@ -0,0 +1,95 @@
+// -*- c++ -*-
+/* Copyright 2016, The libsigc++ Development Team
+ *  Assigned to public domain.  Use as you wish without restriction.
+ */
+
+
+#include <sigc++/tuple_start.h>
+#include <cstdlib>
+#include <cassert>
+
+void test_tuple_type_start()
+{
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_start = sigc::tuple_type_start<type_tuple, 1>::type;
+    using type_tuple_expected = std::tuple<int>;
+
+    static_assert(std::is_same<type_tuple_start, type_tuple_expected>::value,
+        "unexpected type_tuple_start type");
+  }
+
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_start = sigc::tuple_type_start<type_tuple, 2>::type;
+    using type_tuple_expected = std::tuple<int, short>;
+
+    static_assert(std::is_same<type_tuple_start, type_tuple_expected>::value,
+        "unexpected type_tuple_start type");
+  }
+
+  {
+    using type_tuple = std::tuple<int, short, double>;
+    using type_tuple_start = sigc::tuple_type_start<type_tuple, 3>::type;
+    using type_tuple_expected = std::tuple<int, short, double>;
+
+    static_assert(std::is_same<type_tuple_start, type_tuple_expected>::value,
+        "unexpected type_tuple_start type");
+  }
+}
+
+void test_tuple_start()
+{
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_prefix = sigc::tuple_start<3>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_prefix)>::value == 3,
+      "unexpected tuple_start()ed tuple size.");
+
+    assert(std::get<0>(t_prefix) == nullptr);
+    assert(std::get<1>(t_prefix) == "hello");
+    assert(std::get<2>(t_prefix) == "world");
+
+    static_assert(std::is_same<decltype(t_prefix), decltype(t_original)>::value,
+      "unexpected start()ed tuple type");
+  }
+
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_prefix = sigc::tuple_start<2>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_prefix)>::value == 2,
+      "unexpected tuple_start()ed tuple size.");
+      
+    assert(std::get<0>(t_prefix) == nullptr);
+    assert(std::get<1>(t_prefix) == "hello");
+
+    using type_tuple_prefix = std::tuple<std::nullptr_t, std::string>;
+    static_assert(std::is_same<decltype(t_prefix), type_tuple_prefix>::value,
+      "unexpected start()ed tuple type");
+  }
+
+  {
+    auto t_original = std::make_tuple(nullptr, std::string("hello"),
+      std::string("world"));
+    auto t_prefix = sigc::tuple_start<1>(t_original);
+
+    static_assert(std::tuple_size<decltype(t_prefix)>::value == 1,
+      "unexpected tuple_start()ed tuple size.");
+
+    assert(std::get<0>(t_prefix) == nullptr);
+
+    using type_tuple_prefix = std::tuple<std::nullptr_t>;
+    static_assert(std::is_same<decltype(t_prefix), type_tuple_prefix>::value,
+      "unexpected start()ed tuple type");
+  }
+}
+
+int main()
+{  
+  test_tuple_type_start();
+  test_tuple_start();
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]