[libsigc++2/variadic] hide.h.m4: hide_functor::operator(): Make this variadic.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsigc++2/variadic] hide.h.m4: hide_functor::operator(): Make this variadic.
- Date: Thu, 14 Jan 2016 16:43:30 +0000 (UTC)
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]