Commit 86db68ad authored by Dominik Charousset's avatar Dominik Charousset

new class: int_list

this class provides a convenient way to access int parameter packs
in the same way as type_list does for type parameter packs
parent 96871ee5
......@@ -41,6 +41,7 @@ cppa/detail/get_behavior.hpp
cppa/detail/group_manager.hpp
cppa/detail/implicit_conversions.hpp
cppa/detail/matches.hpp
cppa/detail/memory.hpp
cppa/detail/object_array.hpp
cppa/detail/object_impl.hpp
cppa/detail/opt_impls.hpp
......@@ -81,11 +82,13 @@ cppa/get.hpp
cppa/group.hpp
cppa/guard_expr.hpp
cppa/intrusive/single_reader_queue.hpp
cppa/intrusive_fwd_ptr.hpp
cppa/intrusive_ptr.hpp
cppa/local_actor.hpp
cppa/logging.hpp
cppa/match.hpp
cppa/match_expr.hpp
cppa/memory_managed.hpp
cppa/message_future.hpp
cppa/message_id.hpp
cppa/network/acceptor.hpp
......@@ -147,6 +150,7 @@ cppa/util/element_at.hpp
cppa/util/fiber.hpp
cppa/util/fixed_vector.hpp
cppa/util/if_else.hpp
cppa/util/int_list.hpp
cppa/util/is_array_of.hpp
cppa/util/is_builtin.hpp
cppa/util/is_comparable.hpp
......@@ -165,6 +169,7 @@ cppa/util/replace_type.hpp
cppa/util/ripemd_160.hpp
cppa/util/rm_option.hpp
cppa/util/rm_ref.hpp
cppa/util/scope_guard.hpp
cppa/util/shared_lock_guard.hpp
cppa/util/shared_spinlock.hpp
cppa/util/static_foreach.hpp
......@@ -181,6 +186,10 @@ examples/event_based_api/dining_philosophers.cpp
examples/hello_world.cpp
examples/message_passing/dancing_kirby.cpp
examples/message_passing/math_actor.cpp
examples/qtsupport/chatwidget.cpp
examples/qtsupport/chatwidget.hpp
examples/qtsupport/chatwindow.ui
examples/qtsupport/qt_group_chat.cpp
examples/remote_actors/distributed_math_actor.cpp
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_server.cpp
......@@ -228,6 +237,8 @@ src/ipv4_io_stream.cpp
src/local_actor.cpp
src/logging.cpp
src/match.cpp
src/memory.cpp
src/memory_managed.cpp
src/message_header.cpp
src/middleman.cpp
src/object.cpp
......@@ -238,6 +249,7 @@ src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/receive.cpp
src/recursive_queue_node.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
......@@ -275,14 +287,3 @@ unit_testing/test__tuple.cpp
unit_testing/test__type_list.cpp
unit_testing/test__uniform_type.cpp
unit_testing/test__yield_interface.cpp
cppa/detail/memory.hpp
src/memory.cpp
src/recursive_queue_node.cpp
cppa/intrusive_fwd_ptr.hpp
cppa/memory_managed.hpp
src/memory_managed.cpp
examples/qtsupport/qt_group_chat.cpp
examples/qtsupport/chatwindow.ui
examples/qtsupport/chatwidget.hpp
examples/qtsupport/chatwidget.cpp
cppa/util/scope_guard.hpp
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_UTIL_INT_LIST_HPP
#define CPPA_UTIL_INT_LIST_HPP
#include "cppa/util/type_list.hpp"
namespace cppa { namespace util {
/**
* @defgroup MetaProgramming Metaprogramming utility.
*/
/**
* @addtogroup MetaProgramming
* @{
*/
/**
* @brief A list of integers (wraps a long... template parameter pack).
*/
template<long... Ts>
struct int_list { };
/**
* @brief Denotes the empty list.
*/
typedef int_list<> empty_int_list;
template<class List>
struct is_int_list {
static constexpr bool value = false;
};
template<long... Is>
struct is_int_list<int_list<Is...> > {
static constexpr bool value = true;
};
// long head(int_list)
/**
* @brief Gets the first element of @p List.
*/
template<class List>
struct il_head;
template<long I0, long... Is>
struct il_head<int_list<I0,Is...>> {
static constexpr long value = I0;
};
// int_list tail(int_list)
/**
* @brief Gets the tail of @p List.
*/
template<class List>
struct il_tail;
template<>
struct il_tail<empty_int_list> {
typedef empty_int_list type;
};
template<long I0, long... Is>
struct il_tail<int_list<I0,Is...>> {
typedef int_list<Is...> type;
};
// size_t size(int_list)
/**
* @brief Gets the number of elements of @p List.
*/
template<class List>
struct il_size;
template<long... Is>
struct il_size<int_list<Is...>> {
static constexpr size_t value = sizeof...(Is);
};
// T back(int_list)
/**
* @brief Gets the last element in @p List.
*/
template<class List>
struct il_back;
template<long I0>
struct il_back<int_list<I0>> {
static constexpr long value = I0;
};
template<long I0, long I1, long... Is>
struct il_back<int_list<I0,I1,Is...> > {
static constexpr long value = il_back<int_list<I1,Is...>>::value;
};
// bool empty(int_list)
/**
* @brief Tests whether a list is empty.
*/
template<class List>
struct il_empty {
static constexpr bool value = std::is_same<empty_int_list,List>::value;
};
/**
* @brief Gets the minimal value in @p List.
*/
template<class List>
struct il_min;
template<long I0>
struct il_min<int_list<I0>> {
static constexpr long value = I0;
};
template<long I0, long I1, long... Is>
struct il_min<int_list<I0,I1,Is...> > {
static constexpr long value = il_min<int_list<(I0 < I1) ? I0 : I1,Is...>>::value;
};
/**
* @brief Gets the maximum value in @p List.
*/
template<class IndicesPack>
struct il_max;
template<long I0>
struct il_max<int_list<I0>> {
static constexpr long value = I0;
};
template<long I0, long I1, long... Is>
struct il_max<int_list<I0,I1,Is...> > {
static constexpr long value = il_max<int_list<(I0 > I1) ? I0 : I1,Is...>>::value;
};
// list slice(size_t, size_t)
template<size_t LeftOffset, size_t Remaining,
long PadValue, class List, long... Is>
struct il_slice_impl {
typedef typename il_slice_impl<
LeftOffset - 1,
Remaining,
PadValue,
typename il_tail<List>::type,
Is...
>::type
type;
};
template<size_t Remaining, long PadValue, class List, long... Is>
struct il_slice_impl<0, Remaining, PadValue, List, Is...> {
typedef typename il_slice_impl<
0,
Remaining - 1,
PadValue,
typename il_tail<List>::type,
Is...,
il_head<List>::value
>::type
type;
};
template<size_t Remaining, long PadValue, long... Is>
struct il_slice_impl<0, Remaining, PadValue, empty_int_list, Is...> {
typedef typename il_slice_impl<
0,
Remaining - 1,
PadValue,
empty_int_list,
Is...,
PadValue
>::type
type;
};
template<long PadValue, class List, long... Is>
struct il_slice_impl<0, 0, PadValue, List, Is...> {
typedef int_list<Is...> type;
};
template<long PadValue, long... Is>
struct il_slice_impl<0, 0, PadValue, empty_int_list, Is...> {
typedef int_list<Is...> type;
};
template<class List, size_t ListSize, size_t First, size_t Last, long PadValue = 0>
struct il_slice_ {
typedef typename il_slice_impl<First,(Last-First),PadValue,List>::type type;
};
template<class List, size_t ListSize, long PadValue>
struct il_slice_<List,ListSize,0,ListSize,PadValue> {
typedef List type;
};
/**
* @brief Creates a new list from range (First, Last].
*/
template<class List, size_t First, size_t Last>
struct il_slice {
static_assert(First <= Last, "First > Last");
typedef typename il_slice_<List,il_size<List>::value,First,Last>::type type;
};
// list reverse()
template<class List, long... Vs>
struct il_reverse_impl;
template<long I0, long... Is, long... Vs>
struct il_reverse_impl<int_list<I0,Is...>,Vs...> {
typedef typename il_reverse_impl<int_list<Is...>,I0,Vs...>::type type;
};
template<long... Vs>
struct il_reverse_impl<empty_int_list,Vs...> {
typedef int_list<Vs...> type;
};
/**
* @brief Creates a new list wih elements in reversed order.
*/
template<class List>
struct il_reverse {
typedef typename il_reverse_impl<List>::type type;
};
template<class List1, class List2>
struct il_concat_impl;
template<long... As, long... Bs>
struct il_concat_impl<int_list<As...>,int_list<Bs...>> {
typedef int_list<As...,Bs...> type;
};
// static list concat(list, list)
/**
* @brief Concatenates lists.
*/
template<class... Lists>
struct il_concat;
template<class List0>
struct il_concat<List0> {
typedef List0 type;
};
template<class List0, class List1, class... Lists>
struct il_concat<List0,List1,Lists...> {
typedef typename il_concat<
typename il_concat_impl<List0,List1>::type,
Lists...
>::type
type;
};
// list push_back(list, type)
template<class List, long Val>
struct il_push_back;
/**
* @brief Appends @p What to given list.
*/
template<long... Is, long Val>
struct il_push_back<int_list<Is...>,Val> {
typedef int_list<Is...,Val> type;
};
template<class List, long Val>
struct il_push_front;
/**
* @brief Appends @p What to given list.
*/
template<long... Is, long Val>
struct il_push_front<int_list<Is...>,Val> {
typedef int_list<Val,Is...> type;
};
// list pop_back()
/**
* @brief Creates a new list wih all but the last element of @p List.
*/
template<class List>
struct il_pop_back {
typedef typename il_slice<List,0,il_size<List>::value-1>::type type;
};
template<>
struct il_pop_back<empty_int_list> {
typedef empty_int_list type;
};
// type at(size_t)
template<size_t N, long... Is>
struct il_at_impl;
template<size_t N, long I0, long... Is>
struct il_at_impl<N,I0,Is...> : il_at_impl<N-1,Is...> { };
template<long I0, long... Is>
struct il_at_impl<0,I0,Is...> {
static constexpr long value = I0;
};
template<class List, size_t N>
struct il_at;
/**
* @brief Gets element at index @p N of @p List.
*/
template<size_t N, long... E>
struct il_at<int_list<E...>, N> {
static_assert(N < sizeof...(E), "N >= il_size<List>::value");
typedef typename il_at_impl<N, E...>::type type;
};
// list prepend(type)
template<class List, long What>
struct il_prepend;
/**
* @brief Creates a new list with @p What prepended to @p List.
*/
template<long Val, long... Is>
struct il_prepend<int_list<Is...>,Val> {
typedef int_list<Val,Is...> type;
};
// list resize(list, size, fill_type)
template<class List, bool OldSizeLessNewSize,
size_t OldSize, size_t NewSize, long FillVal>
struct il_pad_right_impl;
template<class List, size_t OldSize, size_t NewSize, long FillVal>
struct il_pad_right_impl<List,false,OldSize,NewSize,FillVal> {
typedef typename il_slice<List,0,NewSize>::type type;
};
template<class List, size_t Size, long FillVal>
struct il_pad_right_impl<List,false,Size,Size,FillVal> {
typedef List type;
};
template<class List, size_t OldSize, size_t NewSize, long FillVal>
struct il_pad_right_impl<List, true, OldSize, NewSize, FillVal> {
typedef typename il_pad_right_impl<
typename il_push_back<List, FillVal>::type, (OldSize + 1) < NewSize,
OldSize + 1,
NewSize,
FillVal
>::type
type;
};
/**
* @brief Resizes the list to contain @p NewSize elements and uses
* @p FillVal to initialize the new elements with.
*/
template<class List, size_t NewSize, long FillVal = 0>
struct il_pad_right {
typedef typename il_pad_right_impl<
List, (il_size<List>::value < NewSize), il_size<List>::value, NewSize, FillVal
>::type
type;
};
// bool pad_left(list, N)
template<class List, size_t OldSize, size_t NewSize, long FillVal>
struct il_pad_left_impl {
typedef typename il_pad_left_impl<
typename il_push_front<List, FillVal>::type,
OldSize + 1,
NewSize,
FillVal
>::type
type;
};
template<class List, size_t Size, long FillVal>
struct il_pad_left_impl<List, Size, Size, FillVal> {
typedef List type;
};
/**
* @brief Resizes the list to contain @p NewSize elements and uses
* @p FillVal to initialize prepended elements with.
*/
template<class List, size_t NewSize, long FillVal = 0>
struct il_pad_left {
static constexpr size_t list_size = il_size<List>::value;
//static_assert(NewSize >= il_size<List>::value, "List too big");
typedef typename il_pad_left_impl<
List,
list_size, (list_size > NewSize) ? list_size : NewSize,
FillVal
>::type
type;
};
/**
* @brief Creates the list (From, ..., To)
*/
template<long From, long To, long... Is>
struct il_range {
typedef typename il_range<From,To-1,To,Is...>::type type;
};
template<long X, long... Is>
struct il_range<X,X,Is...> {
typedef int_list<X,Is...> type;
};
/**
* @brief Creates indices for @p List beginning at @p Pos.
*/
template<typename List, long Pos = 0, typename Indices = empty_int_list>
struct il_indices;
template<template<class...> class List, long... Is, long Pos>
struct il_indices<List<>,Pos,int_list<Is...>> {
typedef int_list<Is...> type;
};
template<template<class...> class List, typename T0, typename... Ts, long Pos, long... Is>
struct il_indices<List<T0,Ts...>,Pos,int_list<Is...>> {
// always use type_list to forward remaining Ts... arguments
typedef typename il_indices<type_list<Ts...>,Pos+1,int_list<Is...,Pos>>::type type;
};
template<typename T>
constexpr auto get_indices(const T&) -> typename util::il_indices<T>::type {
return {};
}
/**
* @}
*/
} } // namespace cppa::util
#endif // CPPA_UTIL_INT_LIST_HPP
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment