diff --git a/CMakeLists.txt b/CMakeLists.txt index c632c212..463588e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,7 @@ list ( time.hpp time/parse.hpp time/parse8601.cpp + tuple/index.hpp tuple/type.hpp tuple/value.hpp typeidx.cpp @@ -537,6 +538,7 @@ if (TESTS) thread/ticketlock time/8601 traits + tuple/index tuple/value tuple/type typeidx diff --git a/test/tuple/index.cpp b/test/tuple/index.cpp new file mode 100644 index 00000000..b7193c47 --- /dev/null +++ b/test/tuple/index.cpp @@ -0,0 +1,34 @@ +#include "tap.hpp" +#include "tuple/index.hpp" + + +int +main () +{ + util::TAP::logger tap; + + { + using a_t = util::tuple::index::indices<0,1,2>; + using b_t = util::tuple::index::indices<4,3>; + + using result_t = util::tuple::index::cat::type; + using expected_t = util::tuple::index::indices<0,1,2,4,3>; + + tap.expect (std::is_same_v, "index concatenation"); + } + + { + using indices_t = util::tuple::index::make_indices<4>::type; + using expected_t = util::tuple::index::indices<0,1,2,3>; + + tap.expect (std::is_same_v, "index sequence creation"); + } + + { + using indices_t = util::tuple::index::make_reverse_t<4>; + using expected_t = util::tuple::index::indices<3,2,1,0>; + tap.expect (std::is_same_v, "reverse index sequence creation"); + } + + return tap.status (); +} \ No newline at end of file diff --git a/tuple/index.hpp b/tuple/index.hpp new file mode 100644 index 00000000..d2baf443 --- /dev/null +++ b/tuple/index.hpp @@ -0,0 +1,126 @@ +/* + * 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 2018 Danny Robson + */ + +#ifndef CRUFT_UTIL_TUPLE_VALUE_HPP +#define CRUFT_UTIL_TUPLE_VALUE_HPP + +#include + +/////////////////////////////////////////////////////////////////////////// +// the implementation of all the below must be standalone as they are a +// potential building block in other algorithms and we can't be sure we +// won't create a dependency loop somewhere. +namespace util::tuple::index { + /////////////////////////////////////////////////////////////////////////// + template + struct indices {}; + + + /////////////////////////////////////////////////////////////////////////// + template + struct cat; + + //------------------------------------------------------------------------- + template < + size_t ...A, + size_t ...B + > + struct cat< + indices, + indices + > { + using type = indices; + }; + + + //------------------------------------------------------------------------- + template + using cat_t = typename cat::type; + + + /////////////////////////////////////////////////////////////////////////// + namespace detail { + template + struct make_indices { + using type = cat_t< + typename make_indices::type, + indices + >; + }; + + + template <> + struct make_indices<0> { + using type = indices<>; + }; + }; + + //------------------------------------------------------------------------- + // create a monotonically increasing index sequence over the range [0,N) + template + struct make_indices { + using type = typename detail::make_indices::type; + }; + + //------------------------------------------------------------------------- + template + using make_indices_t = typename make_indices::type; + + + /////////////////////////////////////////////////////////////////////////// + namespace detail { + template + struct make_reverse; + + template + struct make_reverse< + indices + > { + using type = cat_t< + typename make_reverse>::type, + indices + >; + }; + + + template <> + struct make_reverse< + indices<> + > { + using type = indices<>; + }; + }; + + + //------------------------------------------------------------------------- + // create a montonically decreasing index sequence over the range (N-1, 0]. + // + // eg, make_reverse<3> is indices<3,2,1,0> + template + struct make_reverse { + using type = typename detail::make_reverse< + make_indices_t + >::type; + }; + + + //------------------------------------------------------------------------- + template + using make_reverse_t = typename make_reverse::type; +}; + + +#endif