Commit 912f9cd9 authored by Dominik Charousset's avatar Dominik Charousset

improved any_tuple interface

this patch adds the member functions `drop`, `drop_right`, `take`,
and `take_right` to the class `any_tuple`.
parent 6804da2f
......@@ -103,6 +103,7 @@ set(LIBCPPA_SRC
src/context_switching_actor.cpp
src/continuable_reader.cpp
src/continuable_writer.cpp
src/decorated_tuple.cpp
src/default_actor_addressing.cpp
src/default_actor_proxy.cpp
src/default_peer.cpp
......
......@@ -294,3 +294,4 @@ src/get_mac_addresses.cpp
cppa/util/get_root_uuid.hpp
src/get_root_uuid.cpp
cppa/util/type_traits.hpp
src/decorated_tuple.cpp
......@@ -110,7 +110,27 @@ class any_tuple {
/**
* @brief Gets the size of this tuple.
*/
size_t size() const;
inline size_t size() const;
/**
* @brief Creates a new tuple with all but the first n values.
*/
any_tuple drop(size_t n) const;
/**
* @brief Creates a new tuple with all but the last n values.
*/
any_tuple drop_right(size_t n) const;
/**
* @brief Creates a new tuple from the first n values.
*/
inline any_tuple take(size_t n) const;
/**
* @brief Creates a new tuple from the last n values.
*/
inline any_tuple take_right(size_t n) const;
/**
* @brief Gets a mutable pointer to the element at position @p p.
......@@ -310,6 +330,18 @@ inline void any_tuple::force_detach() {
m_vals.detach();
}
inline size_t any_tuple::size() const {
return m_vals->size();
}
inline any_tuple any_tuple::take(size_t n) const {
return n >= size() ? *this : drop_right(size() - n);
}
inline any_tuple any_tuple::take_right(size_t n) const {
return n >= size() ? *this : drop(size() - n);
}
template<typename T, bool IsIterable = true>
struct any_tuple_view_trait_impl {
static constexpr bool is_mutable_ref = std::is_reference<T>::value
......
......@@ -73,7 +73,6 @@ class cow_tuple<Head, Tail...> {
friend class any_tuple;
typedef detail::tuple_vals<Head, Tail...> data_type;
typedef detail::decorated_tuple<Head, Tail...> decorated_type;
cow_ptr<detail::abstract_tuple> m_vals;
......@@ -114,7 +113,8 @@ class cow_tuple<Head, Tail...> {
static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
auto ti = detail::static_type_list<Head, Tail...>::by_offset(offset);
return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, offset)};
}
/**
......@@ -152,9 +152,15 @@ class cow_tuple<Head, Tail...> {
return {priv_ctor{}, std::move(ptr)};
}
static cow_tuple from(cow_ptr_type ptr,
const util::limited_vector<size_t, num_elements>& mv) {
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
static cow_tuple from(cow_ptr_type ptr, std::vector<size_t> mv) {
auto ti = detail::static_type_list<Head, Tail...>::list;
return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, std::move(mv))};
}
static cow_tuple from(cow_ptr_type ptr, const util::limited_vector<size_t, num_elements>& mv) {
std::vector<size_t> v(mv.size());
std::copy(mv.begin(), mv.end(), v.begin());
return from(ptr, std::move(v));
}
inline const cow_ptr<detail::abstract_tuple>& vals() const {
......
......@@ -40,7 +40,6 @@
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/limited_vector.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
......@@ -48,97 +47,72 @@
namespace cppa { namespace detail {
template<typename... Ts>
class decorated_tuple : public abstract_tuple {
typedef abstract_tuple super;
static_assert(sizeof...(Ts) > 0,
"decorated_tuple is not allowed to be empty");
decorated_tuple& operator=(const decorated_tuple&) = delete;
public:
typedef util::limited_vector<size_t, sizeof...(Ts)> vector_type;
typedef std::vector<size_t> vector_type;
typedef cow_ptr<abstract_tuple> cow_pointer_type;
typedef cow_ptr<abstract_tuple> pointer;
static inline cow_pointer_type create(cow_pointer_type d,
const vector_type& v) {
return cow_pointer_type{new decorated_tuple(std::move(d), v)};
}
typedef const std::type_info* rtti;
// creates a subtuple form @p d with an offset
static inline cow_pointer_type create(cow_pointer_type d, size_t offset) {
return cow_pointer_type{new decorated_tuple(std::move(d), offset)};
// creates a dynamically typed subtuple from @p d with an offset
static inline pointer create(pointer d, vector_type v) {
return pointer{new decorated_tuple(std::move(d), std::move(v))};
}
virtual void* mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size());
return m_decorated->mutable_at(m_mapping[pos]);
// creates a statically typed subtuple from @p d with an offset
static inline pointer create(pointer d, rtti ti, vector_type v) {
return pointer{new decorated_tuple(std::move(d), ti, std::move(v))};
}
virtual size_t size() const {
return sizeof...(Ts);
// creates a dynamically typed subtuple from @p d with an offset
static inline pointer create(pointer d, size_t offset) {
return pointer{new decorated_tuple(std::move(d), offset)};
}
virtual decorated_tuple* copy() const {
return new decorated_tuple(*this);
// creates a statically typed subtuple from @p d with an offset
static inline pointer create(pointer d, rtti ti, size_t offset) {
return pointer{new decorated_tuple(std::move(d), ti, offset)};
}
virtual const void* at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mapping[pos]);
}
virtual void* mutable_at(size_t pos) override;
virtual const uniform_type_info* type_at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mapping[pos]);
}
virtual size_t size() const override;
const std::type_info* type_token() const {
return static_type_list<Ts...>::list;
}
virtual decorated_tuple* copy() const override;
virtual const void* at(size_t pos) const override;
virtual const uniform_type_info* type_at(size_t pos) const override;
rtti type_token() const override;
private:
cow_pointer_type m_decorated;
pointer m_decorated;
rtti m_token;
vector_type m_mapping;
decorated_tuple(cow_pointer_type d, const vector_type& v)
: super(false)
, m_decorated(std::move(d)), m_mapping(v) {
# ifdef CPPA_DEBUG_MODE
const cow_pointer_type& ptr = m_decorated; // prevent detaching
# endif
CPPA_REQUIRE(ptr->size() >= sizeof...(Ts));
CPPA_REQUIRE(v.size() == sizeof...(Ts));
CPPA_REQUIRE(*(std::max_element(v.begin(), v.end())) < ptr->size());
}
void init();
decorated_tuple(cow_pointer_type d, size_t offset)
: super(false), m_decorated(std::move(d)) {
# ifdef CPPA_DEBUG_MODE
const cow_pointer_type& ptr = m_decorated; // prevent detaching
# endif
CPPA_REQUIRE((ptr->size() - offset) >= sizeof...(Ts));
CPPA_REQUIRE(offset > 0);
size_t i = offset;
m_mapping.resize(sizeof...(Ts));
std::generate(m_mapping.begin(), m_mapping.end(), [&]() {return i++;});
}
void init(size_t);
decorated_tuple(const decorated_tuple&) = default;
decorated_tuple(pointer, size_t);
decorated_tuple& operator=(const decorated_tuple&) = delete;
decorated_tuple(pointer, rtti, size_t);
};
decorated_tuple(pointer, vector_type&&);
decorated_tuple(pointer, rtti, vector_type&&);
template<typename TypeList>
struct decorated_cow_tuple_from_type_list;
decorated_tuple(const decorated_tuple&) = default;
template<typename... Ts>
struct decorated_cow_tuple_from_type_list< util::type_list<Ts...> > {
typedef decorated_tuple<Ts...> type;
};
} } // namespace cppa::detail
......
......@@ -38,7 +38,6 @@
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail {
......
......@@ -183,14 +183,32 @@ struct static_types_array_from_type_list<util::type_list<T...>> {
typedef static_types_array<T...> type;
};
// utility for singleton-like access to a type_info instance of a type_list
template<typename... T>
struct static_type_list {
struct static_type_list;
template<typename T>
struct static_type_list<T> {
static const std::type_info* list;
static inline const std::type_info* by_offset(size_t offset) {
return offset == 0 ? list : &typeid(util::type_list<>);
}
};
template<typename... T>
const std::type_info* static_type_list<T...>::list = &typeid(util::type_list<T...>);
template<typename T>
const std::type_info* static_type_list<T>::list = &typeid(util::type_list<T>);
// utility for singleton-like access to a type_info instance of a type_list
template<typename T0, typename T1, typename... Ts>
struct static_type_list<T0, T1, Ts...> {
static const std::type_info* list;
static inline const std::type_info* by_offset(size_t offset) {
return offset == 0 ? list : static_type_list<T1, Ts...>::list;
}
};
template<typename T0, typename T1, typename... Ts>
const std::type_info* static_type_list<T0, T1, Ts...>::list = &typeid(util::type_list<T0, T1, Ts...>);
} } // namespace cppa::detail
......
......@@ -53,10 +53,6 @@ void any_tuple::reset() {
m_vals.reset(get_empty_tuple());
}
size_t any_tuple::size() const {
return m_vals->size();
}
void* any_tuple::mutable_at(size_t p) {
return m_vals->mutable_at(p);
}
......@@ -73,4 +69,20 @@ bool any_tuple::equals(const any_tuple& other) const {
return m_vals->equals(*other.vals());
}
any_tuple any_tuple::drop(size_t n) const {
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
return any_tuple{detail::decorated_tuple::create(m_vals, n)};
}
any_tuple any_tuple::drop_right(size_t n) const {
using namespace std;
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
vector<size_t> mapping(size() - n);
size_t i = 0;
generate(mapping.begin(), mapping.end(), [&] { return i++; });
return any_tuple{detail::decorated_tuple::create(m_vals, move(mapping))};
}
} // namespace cppa
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* 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 2.1 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/>. *
\******************************************************************************/
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail {
void* decorated_tuple::mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size());
return m_decorated->mutable_at(m_mapping[pos]);
}
size_t decorated_tuple::size() const {
return m_mapping.size();
}
decorated_tuple* decorated_tuple::copy() const {
return new decorated_tuple(*this);
}
const void* decorated_tuple::at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mapping[pos]);
}
const uniform_type_info* decorated_tuple::type_at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mapping[pos]);
}
auto decorated_tuple::type_token() const -> rtti {
return m_token;
}
void decorated_tuple::init() {
CPPA_REQUIRE( m_mapping.empty()
|| *(std::max_element(m_mapping.begin(), m_mapping.end()))
< static_cast<const pointer&>(m_decorated)->size());
}
void decorated_tuple::init(size_t offset) {
const pointer& dec = m_decorated;
if (offset < dec->size()) {
size_t i = offset;
m_mapping.resize(dec->size() - offset);
std::generate(m_mapping.begin(), m_mapping.end(), [&] {return i++;});
}
init();
}
decorated_tuple::decorated_tuple(pointer d, vector_type&& v)
: super(true), m_decorated(std::move(d)), m_token(&typeid(void)), m_mapping(std::move(v)) {
init();
}
decorated_tuple::decorated_tuple(pointer d, rtti ti, vector_type&& v)
: super(false), m_decorated(std::move(d)), m_token(ti), m_mapping(std::move(v)) {
init();
}
decorated_tuple::decorated_tuple(pointer d, size_t offset)
: super(true), m_decorated(std::move(d)), m_token(&typeid(void)) {
init(offset);
}
decorated_tuple::decorated_tuple(pointer d, rtti ti, size_t offset)
: super(false), m_decorated(std::move(d)), m_token(ti) {
init(offset);
}
} } // namespace cppa::detail
......@@ -395,6 +395,13 @@ void check_wildcards() {
CPPA_CHECK(&get<0>(*opt3) == at1.at(0));
CPPA_CHECK(&get<1>(*opt3) == at1.at(3));
}
auto opt4 = tuple_cast<anything, double>(at1);
CPPA_CHECK(opt4);
if (opt4) {
CPPA_CHECK((*opt4 == make_any_tuple(4.0)));
CPPA_CHECK_EQUAL(get<0>(*opt4), 4.0);
CPPA_CHECK(&get<0>(*opt4) == at1.at(3));
}
}
}
......@@ -409,6 +416,26 @@ void check_move_ops() {
CPPA_CHECK_EQUAL(s_expensive_copies.load(), 0);
}
void check_drop() {
CPPA_PRINT(__func__);
auto t0 = make_any_tuple(0, 1, 2, 3);
auto t1 = t0.drop(2);
CPPA_CHECK_EQUAL(t1.size(), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(0), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(1), 3);
CPPA_CHECK(t1 == make_any_tuple(2, 3));
auto t2 = t0.drop_right(2);
CPPA_CHECK_EQUAL(t2.size(), 2);
CPPA_CHECK_EQUAL(t2.get_as<int>(0), 0);
CPPA_CHECK_EQUAL(t2.get_as<int>(1), 1);
CPPA_CHECK(t2 == make_any_tuple(0, 1));
CPPA_CHECK(t0.take(3) == t0.drop_right(1));
CPPA_CHECK(t0.take_right(3) == t0.drop(1));
CPPA_CHECK(t0 == t0.take(4));
CPPA_CHECK(t0.take(4) == t0.take_right(20));
CPPA_CHECK(t0.take(0).empty());
}
int main() {
CPPA_TEST(test_tuple);
announce<expensive_copy_struct>(&expensive_copy_struct::value);
......@@ -417,6 +444,7 @@ int main() {
check_guards();
check_wildcards();
check_move_ops();
check_drop();
await_all_others_done();
shutdown();
return CPPA_TEST_RESULT();
......
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