Skip to content

Commit

Permalink
Improve library layout
Browse files Browse the repository at this point in the history
 - Rename:
  - `first` to `front`
  - `last` to `back`
  - `not_first` to `pop_front`
  - `not_last` to `pop_back`
 - Introduce `cat` in place of `merge`
 - Introduce `extract::none`, `pack`, `size`, `unpack`
 - Introduce direct pack operators (`pack_cat`, `pack_clear`, `pack_size`)
 - Introduce shorthands for `type_frame` and `templated_type_frame`
 - Add loose operators as nested using declarations in `collection` 
 - Every operator is defined as struct (and introduce def.hpp header) to solve cross references problem
 - Progress documentation
 - Progress unit tests with new library layout
  • Loading branch information
md committed Mar 22, 2017
1 parent b274d8b commit 9fe12b6
Show file tree
Hide file tree
Showing 28 changed files with 989 additions and 443 deletions.
40 changes: 22 additions & 18 deletions project/include/variadic/at.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,54 @@

#pragma once

#include <type_traits>
#include <utility>

#include <variadic/def.hpp>
#include <variadic/type_frame.hpp>

namespace variadic
{

// template <size_t Idx, typename... Types>
// struct at;
namespace detail
{

// template <typename T, typename... Types>
// struct at<0, T, Types...>
// {
// using type = T;
// };
// template <size_t Idx, typename... Types>
// struct at_impl;

// template <size_t Idx, typename T, typename... Types>
// struct at<Idx, T, Types...>
// {
// using type = typename at<Idx - 1, Types...>::type;
// };
// template <typename T, typename... Types>
// struct at_impl<0, T, Types...>
// {
// using type = T;
// };

namespace detail
{
// template <size_t Idx, typename T, typename... Types>
// struct at_impl<Idx, T, Types...>
// {
// using type = typename at<Idx - 1, Types...>::type;
// };

template <size_t Idx, typename = std::make_index_sequence<Idx>>
struct at_frame_impl;
struct at_impl;

template <size_t Idx, size_t... Ignore>
struct at_frame_impl<Idx, std::index_sequence<Ignore...>>
struct at_impl<Idx, std::index_sequence<Ignore...>>
{
template <typename T>
static T deducer(decltype((void*)Ignore)..., T*, ...);
};

template <size_t Idx, typename... Types>
using at_frame = decltype(at_frame_impl<Idx>::deducer(static_cast<type_frame<Types>*>(nullptr)...));
using at_impl_shortcut = decltype(at_impl<Idx>::deducer(static_cast<type_frame<Types>*>(nullptr)...));

} // namespace detail

template <size_t Idx, typename... Types>
struct at
{
using type = typename detail::at_frame<Idx, Types...>::type;
static_assert(Idx < sizeof...(Types), "Index out of range");

using type = typename detail::at_impl_shortcut<Idx, Types...>::type;
};

} // namespace variadic
79 changes: 79 additions & 0 deletions project/include/variadic/back.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright Marek Dalewski 2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <utility>

#include <variadic/at.hpp>
#include <variadic/collection.hpp>
#include <variadic/def.hpp>

namespace variadic
{

namespace detail
{

// template <typename... Types>
// struct back_impl;

// template <>
// struct back_impl<>
// {};

// template <typename T>
// struct back_impl<T>
// {
// using type = T;
// };

// template <typename T, typename Y, typename... Types>
// struct back_impl<T, Y, Types...>
// {
// using type = typename back<Y, Types...>::type;
// };

template <typename... Types>
struct back_impl;

template <>
struct back_impl<>
{};

template <typename T, typename... Types>
struct back_impl<T, Types...>
{
using type = typename at<sizeof...(Types), T, Types...>::type;
};

template <class Sequence, typename... Types>
struct pop_back_impl;

template <size_t... Idxs, typename... Types>
struct pop_back_impl<std::index_sequence<Idxs...>, Types...>
{
using types = collection<typename at<Idxs, Types...>::type...>;
};

} // namespace detail

template <typename... Types>
struct back
{
static_assert(sizeof...(Types) > 0, "No back item in empty template parametr pack");

using type = typename detail::back_impl<Types...>::type;
};

template <typename... Types>
struct pop_back
{
static_assert(sizeof...(Types) > 0, "No not back item(s) in empty template parametr pack");

using types = typename detail::pop_back_impl<std::make_index_sequence<sizeof...(Types) - 1>, Types...>::types;
};

} // namespace variadic
74 changes: 74 additions & 0 deletions project/include/variadic/cat.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright Marek Dalewski 2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <variadic/collection.hpp>
#include <variadic/def.hpp>
#include <variadic/pack.hpp>

namespace variadic
{

namespace detail
{

// template <typename ResultCollection, typename... Collections>
// struct pack_cat_impl;

// template <typename ResultCollection>
// struct pack_cat_impl<ResultCollection>
// {
// using types = ResultCollection;
// };

// template <typename ResultCollection, typename C0, typename... Collections>
// struct pack_cat_impl<ResultCollection, C0, Collections...>
// {
// using types = typename pack_cat_impl<typename C0::template emplace<ResultCollection::template push_back>, Collections...>::types;
// };

template <typename FirstCollection, typename... Collections>
struct pack_cat_impl__collections;

template <typename FirstCollection>
struct pack_cat_impl__collections<FirstCollection>
{
using types = FirstCollection;
};

template <typename FirstCollection, typename NextCollection, typename... Collections>
struct pack_cat_impl__collections<FirstCollection, NextCollection, Collections...>
{
using types = typename pack_cat_impl__collections<typename NextCollection::template emplace<FirstCollection::template push_back>, Collections...>::types;
};

template <typename... Packs>
struct pack_cat_impl
{
using types = typename pack_cat_impl__collections<collection<>, typename unpack_impl<Packs>::types...>::types;
};

} // namespace detail

template <typename... Packs>
struct pack_cat
{
using types = typename detail::pack_cat_impl<Packs...>::types;
};

template <typename... Types>
struct cat
{
template <typename... OtherTypes>
using with = cat<Types..., OtherTypes...>;

template <typename... Packs>
using with_pack = typename pack_cat<collection<Types...>, Packs...>::types::template emplace<cat>;

using types = collection<Types...>;
};

} // namespace variadic
36 changes: 36 additions & 0 deletions project/include/variadic/clear.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright Marek Dalewski 2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <variadic/def.hpp>

namespace variadic
{

namespace detail
{

template <typename Pack>
struct pack_clear_impl
{};

template <template <typename...> typename Pack, typename... Packed>
struct pack_clear_impl<Pack<Packed...>>
{
template <typename... Types>
using type = Pack<Types...>;
};

} // namespace detail

template <typename Pack>
struct pack_clear
{
template <typename... Types>
using type = typename detail::pack_clear_impl<Pack>::template type<Types...>;
};

} // namespace variadic
101 changes: 101 additions & 0 deletions project/include/variadic/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,126 @@

#pragma once

#include <variadic/def.hpp>

namespace variadic
{

///
/// \brief Handler for a collection of types
///
/// \tparam Types collection types
///
template <typename... Types>
struct collection
{
///
/// \brief Self typedef
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::types` is equivalent to `collection<t0, t1, t2>`.
///
using types = collection<Types...>;

///
/// \brief Emplace collection in another handler
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::emplace<std::tuple>` is equivalent to `std::tuple<t0, t1, t2>`.
///
template <template <typename...> typename Parent>
using emplace = Parent<Types...>;

///
/// \brief Wrap every item with wrapping type
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::wrap<std::uinque_ptr>` is equivalent to `collection<std::uinque_ptr<t0>, std::uinque_ptr<t1>, std::uinque_ptr<t2>>`.
///
template <template <typename> typename Wrapper>
using wrap = collection<Wrapper<Types>...>;

///
/// \brief Pushes item to back of collection
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`) and types `ot0`, `ot1`:
/// - expression `c::push_back<>` is equivalent to `collection<t0, t1, t2>`,
/// - expression `c::push_back<ot0>` is equivalent to `collection<t0, t1, t2, ot0>`,
/// - expression `c::push_back<ot0, ot1>` is equivalent to `collection<t0, t1, t2, ot0, ot1>`.
///
template <typename... OtherTypes>
using push_back = collection<Types..., OtherTypes...>;

///
/// \brief Pushes item to front of collection
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`) and types `ot0`, `ot1`:
/// - expression `c::push_front<>` is equivalent to `collection<t0, t1, t2>`,
/// - expression `c::push_front<ot0>` is equivalent to `collection<ot0, t0, t1, t2>`,
/// - expression `c::push_front<ot0, ot1>` is equivalent to `collection<ot0, ot1, t0, t1, t2>`.
///
template <typename... OtherTypes>
using push_front = collection<OtherTypes..., Types...>;

///
/// \brief Allow to access nth item in collection
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`):
/// - expression `c::at<0>` is equivalent to `t0`,
/// - expression `c::at<1>` is equivalent to `t1`,
/// - expression `c::at<2>` is equivalent to `t2`,
/// - putting any value `N`, other than 0, 1 or 2, as template parameter to `c::at<N>` cause compilation error.
///
/// Expression `collection<>::at<N>` for any value `N` (for empty collection), cause compilation error.
///
template <size_t Idx>
using at = typename at<Idx, Types...>::type;

///
/// \brief Allow to access first item in collection
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::front<>` is equivalent to `t0`.
///
/// Expression `collection<>::front<>` (for empty collection), cause compilation error.
///
template <template <typename...> typename Extractor = front>
using front = typename Extractor<Types...>::type;

///
/// \brief Equivalent to collection with first item from current collection extracted
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::pop_front<>` is equivalent to `collection<t1, t2>`.
///
/// Expression `collection<>::pop_front<>` (for empty collection), cause compilation error.
///
template <template <typename...> typename Extractor = pop_front>
using pop_front = typename Extractor<Types...>::types;

///
/// \brief Allow to access last item in collection
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::back<>` is equivalent to `t2`.
///
/// Expression `collection<>::back<>` (for empty collection), cause compilation error.
///
template <template <typename...> typename Extractor = back>
using back = typename Extractor<Types...>::type;

///
/// \brief Equivalent to collection with last item from current collection extracted
///
/// Considering collection `c` of types `t0`, `t1` and `t2` (`typedef collection<t0, t1, t2> c`), expression `c::pop_back<>` is equivalent to `collection<t0, t1>`.
///
/// Expression `collection<>::pop_back<>` (for empty collection), cause compilation error.
///
template <template <typename...> typename Extractor = pop_back>
using pop_back = typename Extractor<Types...>::types;

///
/// \brief Size of collection
///
static constexpr size_t size = sizeof...(Types);

///
/// \brief true if collection is empty, false otherwise
///
static constexpr bool empty = sizeof...(Types) == 0;
};

Expand Down
Loading

0 comments on commit 9fe12b6

Please sign in to comment.