From fa8387252e9702f596b2632ca6297f7d99ff9cc9 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 20 Apr 2015 17:16:18 +1000 Subject: [PATCH] tuple: add tuple iteration helpers --- Makefile.am | 3 ++ test/tuple.cpp | 38 +++++++++++++++++++ tuple.cpp | 19 ++++++++++ tuple.hpp | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 test/tuple.cpp create mode 100644 tuple.cpp create mode 100644 tuple.hpp diff --git a/Makefile.am b/Makefile.am index c7cead25..a54a3a02 100644 --- a/Makefile.am +++ b/Makefile.am @@ -176,6 +176,8 @@ UTIL_FILES = \ tap.ipp \ time.cpp \ time.hpp \ + tuple.cpp \ + tuple.hpp \ types.hpp \ types/bits.hpp \ types/casts.hpp \ @@ -284,6 +286,7 @@ TEST_BIN = \ test/sha2 \ test/signal \ test/stringid \ + test/tuple \ test/uri \ test/vector \ test/version diff --git a/test/tuple.cpp b/test/tuple.cpp new file mode 100644 index 00000000..ed4441c3 --- /dev/null +++ b/test/tuple.cpp @@ -0,0 +1,38 @@ +#include "tuple.hpp" + +#include "tap.hpp" + +#include + +int +main () +{ + util::TAP::logger tap; + + { + auto tuple = std::make_tuple (1,2,3,4); + std::vector expected {{ 1, 2, 3, 4 }}; + + std::vector actual; + util::for_each ([&actual] (auto i) { actual.push_back (i); }, tuple); + + tap.expect_eq (actual, expected, "value iteration"); + } + + { + auto tuple = std::make_tuple (1u, 1, 1.f, 1.); + std::vector expected { + std::type_index (typeid (1u)), + std::type_index (typeid (1)), + std::type_index (typeid (1.f)), + std::type_index (typeid (1.)) + }; + + std::vector actual; + util::for_type ([&actual] (auto i) { + actual.push_back (typeid (typename decltype(i)::type)); + }); + + tap.expect_eq (actual, expected, "type iteration"); + } +} diff --git a/tuple.cpp b/tuple.cpp new file mode 100644 index 00000000..d470aaa9 --- /dev/null +++ b/tuple.cpp @@ -0,0 +1,19 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2015 Danny Robson + */ + +#include "tuple.hpp" + +// Make sure _someone_ includes the header for syntax checking diff --git a/tuple.hpp b/tuple.hpp new file mode 100644 index 00000000..1e8c4e8e --- /dev/null +++ b/tuple.hpp @@ -0,0 +1,100 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2015 Danny Robson + */ + +#ifndef __UTIL_TUPLE_HPP +#define __UTIL_TUPLE_HPP + +#include "types.hpp" + +#include +#include + + +namespace util { + /////////////////////////////////////////////////////////////////////////// + /// call a provided object with type_tag for each type in a tuple + template < + typename T, + typename F, + size_t S = 0 + > + typename std::enable_if< + S == std::tuple_size::value, + void + >::type + for_type (F) + { } + + + //------------------------------------------------------------------------- + template< + typename T, + typename F, + size_t S = 0 + > + typename std::enable_if< + S < std::tuple_size::value, + void + >::type + for_type (F f) + { + using E = typename std::tuple_element::type; + + f (type_tag {}); + for_type (f); + } + + + //------------------------------------------------------------------------- + template + auto for_type (F f, T t) + { return for_type (f); } + + + /////////////////////////////////////////////////////////////////////////// + /// call a provided object with each value in a tuple + template < + size_t S = 0, + typename F, + typename ...T + > + typename std::enable_if< + S == sizeof...(T), + void + >::type + for_each (F, const std::tuple&) + { } + + + //------------------------------------------------------------------------- + template< + size_t S = 0, + typename F, + typename ...T + > + typename std::enable_if< + S < sizeof...(T), + void + >::type + for_each (F f, const std::tuple &t) + { + f (std::get (t)); + for_each (f, t); + } +} + + +#endif