Commit d31dbe5d authored by Dominik Charousset's avatar Dominik Charousset

new iterator interface

parent b453aabb
......@@ -31,15 +31,16 @@
#ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP
#include "cppa/cow_ptr.hpp"
#include "cppa/tuple.hpp"
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa {
/**
* @brief Describes a fixed-length tuple with elements of any type.
* @brief Describes a fixed-length copy-on-write tuple
* with elements of any type.
*/
class any_tuple
{
......@@ -61,6 +62,12 @@ class any_tuple
template<typename... Args>
any_tuple(tuple<Args...> const& t) : m_vals(t.vals()) { }
/**
* @brief Creates a tuple and moves the content from @p t.
*/
template<typename... Args>
any_tuple(tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { }
explicit any_tuple(detail::abstract_tuple*);
/**
......@@ -83,45 +90,60 @@ class any_tuple
*/
any_tuple& operator=(any_tuple const&) = default;
/**
* @brief Gets the size of this tuple.
*/
size_t size() const;
/**
* @brief Gets a mutable pointer to the element at position @p p.
*/
void* mutable_at(size_t p);
/**
* @brief Gets a const pointer to the element at position @p p.
*/
void const* at(size_t p) const;
/**
* @brief Gets {@link uniform_type_info uniform type information}
* of the element at position @p p.
*/
uniform_type_info const* type_at(size_t p) const;
cow_ptr<detail::abstract_tuple> const& vals() const;
/**
* @brief Returns @c true if <tt>*this == other</tt>, otherwise false.
*/
bool equals(any_tuple const& other) const;
std::type_info const& impl_type() const;
/**
* @brief Returns true if <tt>size() == 0</tt>, otherwise false.
*/
inline bool empty() const { return size() == 0; }
inline bool empty() const
template<typename T>
inline T const& get_as(size_t p) const
{
return size() == 0;
CPPA_REQUIRE(type_at(p) == typeid(T));
return *reinterpret_cast<T const*>(at(p));
}
template<typename T>
inline T const& get_as(size_t p) const;
inline T& get_mutable_as(size_t p)
{
CPPA_REQUIRE(type_at(p) == typeid(T));
return *reinterpret_cast<T*>(mutable_at(p));
}
template<typename T>
inline T& get_mutable_as(size_t p);
typedef type_value_pair const* const_iterator;
class const_iterator
{
any_tuple const& ref;
size_t p;
public:
inline const_iterator(any_tuple const& data, size_t pos = 0)
: ref(data), p(pos) { }
inline void next() { ++p; }
inline bool at_end() const { return p >= ref.size(); }
inline void const* value() const { return ref.at(p); }
inline uniform_type_info const* type() const { return ref.type_at(p); }
};
inline const_iterator begin() const { return {*this}; }
inline const_iterator begin() const { return m_vals->begin(); }
inline const_iterator end() const { return m_vals->end(); }
std::type_info const& impl_type() const;
cow_ptr<detail::abstract_tuple> const& vals() const;
};
......@@ -135,18 +157,6 @@ inline bool operator!=(any_tuple const& lhs, any_tuple const& rhs)
return !(lhs == rhs);
}
template<typename T>
inline T const& any_tuple::get_as(size_t p) const
{
return *reinterpret_cast<T const*>(at(p));
}
template<typename T>
inline T& any_tuple::get_mutable_as(size_t p)
{
return *reinterpret_cast<T*>(mutable_at(p));
}
} // namespace cppa
#endif // ANY_TUPLE_HPP
......@@ -35,6 +35,8 @@
#include <list>
#include <vector>
#include <utility>
#include <iterator>
#include <algorithm>
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
......@@ -52,8 +54,7 @@ namespace cppa {
class any_tuple_view
{
typedef std::vector< std::pair<uniform_type_info const*, void*> >
vector_type;
typedef std::vector<type_value_pair> vector_type;
vector_type m_values;
......@@ -80,22 +81,14 @@ class any_tuple_view
any_tuple_view(any_tuple& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.mutable_at(i)));
}
}
/*
template<typename... T>
explicit any_tuple_view(tuple<T...> const& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
if (tup.size() > 0)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
// force tuple to detach
tup.mutable_at(0);
std::back_insert_iterator<vector_type> back_iter{m_values};
std::copy(tup.begin(), tup.end(), back_iter);
}
}
*/
template<typename... T>
any_tuple_view(tuple_view<T...> const& tup)
......@@ -137,7 +130,7 @@ class any_tuple_view
inline void const* at(size_t p) const { return m_values[p].second; }
void* mutable_at(size_t p) { return m_values[p].second; }
void* mutable_at(size_t p) { return const_cast<void*>(m_values[p].second); }
inline uniform_type_info const* type_at(size_t p) const
{
......@@ -159,21 +152,11 @@ class any_tuple_view
return typeid(detail::object_array);
}
class const_iterator
{
typedef typename vector_type::const_iterator vec_iterator;
vec_iterator pos;
vec_iterator end;
public:
inline const_iterator(any_tuple_view const& view)
: pos(view.m_values.begin()), end(view.m_values.end()) { }
inline void next() { ++pos; }
inline bool at_end() const { return pos == end; }
inline void const* value() const { return pos->second; }
inline uniform_type_info const* type() const { return pos->first; }
};
inline const_iterator begin() const { return {*this}; }
typedef type_value_pair const* const_iterator;
inline const_iterator begin() const { return m_values.data(); }
inline const_iterator end() const { return begin() + m_values.size(); }
};
......
......@@ -48,6 +48,8 @@ struct abstract_tuple : ref_counted
virtual void* mutable_at(size_t pos) = 0;
// accessors
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual size_t size() const = 0;
virtual abstract_tuple* copy() const = 0;
virtual void const* at(size_t pos) const = 0;
......
......@@ -51,30 +51,42 @@ template<typename... ElementTypes>
class decorated_tuple : public abstract_tuple
{
static_assert(sizeof...(ElementTypes) > 0,
"decorated_tuple is not allowed to be empty");
public:
typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type;
typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(ptr_type&& d, vector_type const& v)
: m_decorated(std::move(d)), m_mappings(v)
using abstract_tuple::const_iterator;
decorated_tuple(ptr_type&& d, vector_type const& v) : m_decorated(std::move(d))
{
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(std::max_element(v.begin(), v.end()) < m_decorated->size());
init(v);
}
decorated_tuple(ptr_type const& d, vector_type const& v)
: m_decorated(d), m_mappings(v)
decorated_tuple(ptr_type const& d, vector_type const& v) : m_decorated(d)
{
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(v.empty() || *(std::max_element(v.begin(), v.end())) < m_decorated->size());
init(v);
}
virtual const_iterator begin() const
{
return m_data;
}
virtual const_iterator end() const
{
return static_cast<const_iterator>(m_data) + sizeof...(ElementTypes);
}
virtual void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
return m_decorated->mutable_at(m_mappings[pos]);
// const_cast is safe because decorated_tuple is used in cow_ptrs only
return const_cast<void*>(m_data[pos].second);
}
virtual size_t size() const
......@@ -90,18 +102,13 @@ class decorated_tuple : public abstract_tuple
virtual void const* at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mappings[pos]);
return m_data[pos].second;
}
virtual uniform_type_info const* type_at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mappings[pos]);
}
virtual bool equals(abstract_tuple const&) const
{
return false;
return m_data[pos].first;
}
virtual std::type_info const& impl_type() const
......@@ -109,17 +116,29 @@ class decorated_tuple : public abstract_tuple
return typeid(decorated_tuple);
}
private:
ptr_type m_decorated;
vector_type m_mappings;
type_value_pair m_data[sizeof...(ElementTypes)];
decorated_tuple(decorated_tuple const& other)
: abstract_tuple()
, m_decorated(other.m_decorated)
, m_mappings(other.m_mappings)
{
// both instances point to the same data
std::copy(other.begin(), other.end(), m_data);
}
void init(vector_type const& v)
{
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(*(std::max_element(v.begin(), v.end())) < m_decorated->size());
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
auto x = v[i];
m_data[i].first = m_decorated->type_at(x);
m_data[i].second = m_decorated->at(x);
}
}
decorated_tuple& operator=(decorated_tuple const&) = delete;
......
......@@ -35,9 +35,13 @@
namespace cppa { namespace detail {
struct empty_tuple : cppa::detail::abstract_tuple
struct empty_tuple : abstract_tuple
{
using abstract_tuple::const_iterator;
const_iterator begin() const;
const_iterator end() const;
size_t size() const;
void* mutable_at(size_t);
abstract_tuple* copy() const;
......
......@@ -31,10 +31,12 @@
#ifndef DO_MATCH_HPP
#define DO_MATCH_HPP
#include <algorithm>
#include <type_traits>
#include "cppa/pattern.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
......@@ -43,42 +45,17 @@
namespace cppa { namespace detail {
template<class T, typename Iterator>
class cppa_iterator_decorator
template<typename T>
inline auto ptr_type(T& ptr, util::enable_if<std::is_pointer<T>>* = 0) -> T
{
return ptr;
}
static types_array<T> tarr;
Iterator begin;
Iterator end;
size_t pos;
uniform_type_info const* t;
public:
cppa_iterator_decorator(Iterator first, Iterator last)
: begin(first), end(last), pos(0), t(tarr[0])
{
}
inline void next()
{
++begin;
++pos;
}
inline bool at_end() const { return begin == end; }
inline uniform_type_info const* type() const { return t; }
inline void const* value() const { return &(*begin); }
inline size_t position() const { return pos; }
};
template<class T, typename Iterator>
types_array<T> cppa_iterator_decorator<T, Iterator>::tarr;
template<typename T>
inline auto ptr_type(T& iter, util::disable_if<std::is_pointer<T>>* = 0) -> decltype(iter.operator->())
{
return iter.operator->();
}
template<class MappingVector, typename Iterator>
class push_mapping_decorator
......@@ -86,58 +63,65 @@ class push_mapping_decorator
size_t pos;
Iterator iter;
MappingVector* mapping;
MappingVector& mapping;
size_t commited_size;
public:
typedef MappingVector mapping_vector;
push_mapping_decorator(Iterator const& i, MappingVector* mv)
: pos(0), iter(i), mapping(mv)
push_mapping_decorator(Iterator const& i, MappingVector& mv)
: pos(0), iter(i), mapping(mv), commited_size(0)
{
}
push_mapping_decorator(push_mapping_decorator const& other,
MappingVector* mv)
: pos(other.pos), iter(other.iter), mapping(mv)
push_mapping_decorator(push_mapping_decorator const&) = default;
inline push_mapping_decorator& operator++()
{
++pos;
++iter;
return *this;
}
inline bool operator==(Iterator const& i)
{
return iter == i;
}
inline decltype(*iter) operator*()
{
return *iter;
}
push_mapping_decorator(push_mapping_decorator&& other)
: pos(other.pos), iter(std::move(other.iter)), mapping(other.mapping)
inline decltype(ptr_type(iter)) operator->()
{
return ptr_type(iter);
}
inline void next() { ++pos; iter.next(); }
inline bool at_end() const { return iter.at_end(); }
inline void const* value() const { return iter.value(); }
inline decltype(iter.type()) type() const { return iter.type(); }
inline bool has_mapping() const { return mapping != nullptr; }
inline void push_mapping()
{
if (mapping) mapping->push_back(pos);
mapping.push_back(pos);
}
inline void commit_mapping()
{
commited_size = mapping.size();
}
inline void push_mapping(MappingVector const& mv)
inline void rollback_mapping()
{
if (mapping) mapping->insert(mapping->end(), mv.begin(), mv.end());
mapping.resize(commited_size);
}
};
template<typename Iterator, class MappingVector>
push_mapping_decorator<MappingVector, Iterator> pm_decorated(Iterator i, MappingVector* mv)
push_mapping_decorator<MappingVector, Iterator> pm_decorated(Iterator i, MappingVector& mv)
{
return {i, mv};
}
template<typename Iterator>
auto ci_decorated(Iterator begin, Iterator end)
-> cppa_iterator_decorator<typename util::rm_ref<decltype(*begin)>::type,
Iterator>
{
return {begin, end};
}
template<typename T>
class is_pm_decorated
{
......@@ -158,11 +142,44 @@ class is_pm_decorated
};
template<class TupleIterator, class PatternIterator>
auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
-> typename util::enable_if_c<is_pm_decorated<TupleIterator>::value,bool>::type
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
push_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
push_mapping(T& iter)
{
iter->push_mapping();
}
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
commit_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
commit_mapping(T& iter)
{
iter->commit_mapping();
}
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
rollback_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
rollback_mapping(T& iter)
{
iter->rollback_mapping();
}
template<class TupleBeginIterator, class TupleEndIterator, class PatternIterator>
bool matches(TupleBeginIterator tbegin, TupleEndIterator tend,
PatternIterator pbegin, PatternIterator pend)
{
for ( ; !(pbegin == pend && targ.at_end()); ++pbegin, targ.next())
for ( ; !(pbegin == pend && tbegin == tend); ++pbegin, ++tbegin)
{
if (pbegin == pend)
{
......@@ -177,27 +194,25 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
// always true at the end of the pattern
return true;
}
typename TupleIterator::mapping_vector mv;
auto mv_ptr = (targ.has_mapping()) ? &mv : nullptr;
// safe current mapping as fallback
commit_mapping(tbegin);
// iterate over tu_args until we found a match
for ( ; targ.at_end() == false; mv.clear(), targ.next())
for (; tbegin != tend; ++tbegin)
{
if (matches(TupleIterator(targ, mv_ptr), pbegin, pend))
{
targ.push_mapping(mv);
return true;
}
if (matches(tbegin, tend, pbegin, pend)) return true;
// restore mapping to fallback (delete invalid mappings)
rollback_mapping(tbegin);
}
return false; // no submatch found
}
// compare types
else if (targ.at_end() == false && pbegin->first == targ.type())
else if (tbegin != tend && pbegin->first == tbegin->first)
{
// compare values if needed
if ( pbegin->second == nullptr
|| pbegin->first->equals(pbegin->second, targ.value()))
|| pbegin->first->equals(pbegin->second, tbegin->second))
{
targ.push_mapping();
push_mapping(tbegin);
}
else
{
......@@ -212,59 +227,13 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
return true; // pbegin == pend && targ.at_end()
}
template<class TupleIterator, class PatternIterator>
auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
-> typename util::enable_if_c<!is_pm_decorated<TupleIterator>::value,bool>::type
{
for ( ; !(pbegin == pend && targ.at_end()); ++pbegin, targ.next())
{
if (pbegin == pend)
{
return false;
}
else if (pbegin->first == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
if (pbegin == pend)
{
// always true at the end of the pattern
return true;
}
// iterate over tu_args until we found a match
for ( ; targ.at_end() == false; targ.next())
{
if (matches(targ, pbegin, pend))
{
return true;
}
}
return false; // no submatch found
}
// compare types
else if (targ.at_end() == false && pbegin->first == targ.type())
{
// compare values if needed
if ( pbegin->second != nullptr
&& !pbegin->first->equals(pbegin->second, targ.value()))
{
return false; // values didn't match
}
}
else
{
return false; // no match
}
}
return true; // pbegin == pend && targ.at_end()
}
// pattern does not contain "anything"
template<class Tuple, class Pattern>
bool matches(std::integral_constant<int, 0>,
Tuple const& tpl, Pattern const& pttrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv)
{
// assertion "tpl.size() == pttrn.size()" is guaranteed from caller
typedef typename Pattern::types ptypes;
typedef typename decorated_tuple_from_type_list<ptypes>::type dec_t;
typedef typename tuple_vals_from_type_list<ptypes>::type tv_t;
......@@ -273,18 +242,17 @@ bool matches(std::integral_constant<int, 0>,
{
if (pttrn.has_values())
{
size_t i = 0;
auto end = pttrn.end();
for (auto iter = pttrn.begin(); iter != end; ++iter)
// compare values only (types are guaranteed to be equal)
auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
{
// pattern (rhs) does not have to have a value
return rhs.second == nullptr
|| lhs.first->equals(lhs.second, rhs.second);
};
if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{
if (iter->second)
{
if (iter->first->equals(iter->second, tpl.at(i)) == false)
{
return false;
}
}
++i;
// values differ
return false;
}
}
}
......@@ -292,25 +260,31 @@ bool matches(std::integral_constant<int, 0>,
{
if (pttrn.has_values())
{
size_t i = 0;
auto end = pttrn.end();
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i)
// compares type and value
auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
{
if (iter->first != tpl.type_at(i)) return false;
if (iter->second)
{
if (iter->first->equals(iter->second, tpl.at(i)) == false)
return false;
}
// pattern (rhs) does not have to have a value
return lhs.first == rhs.first
&& ( rhs.second == nullptr
|| lhs.first->equals(lhs.second, rhs.second));
};
if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{
// types or values differ
return false;
}
}
else
{
size_t i = 0;
auto end = pttrn.end();
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i)
// compares the types only
auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
{
return lhs.first == rhs.first;
};
if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{
if (iter->first != tpl.type_at(i)) return false;
// types differ
return false;
}
}
}
......@@ -369,8 +343,8 @@ bool matches(std::integral_constant<int, 2>,
util::fixed_vector<size_t, Pattern::filtered_size>* mv = 0)
{
if (mv)
return matches(pm_decorated(tpl.begin(), mv), ptrn.begin(), ptrn.end());
return matches(tpl.begin(), ptrn.begin(), ptrn.end());
return matches(pm_decorated(tpl.begin(), *mv), tpl.end(), ptrn.begin(), ptrn.end());
return matches(tpl.begin(), tpl.end(), ptrn.begin(), ptrn.end());
}
template<class Tuple, class Pattern>
......
......@@ -34,32 +34,37 @@
#include <vector>
#include "cppa/object.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa { namespace detail {
class object_array : public detail::abstract_tuple
class object_array : public abstract_tuple
{
std::vector<object> m_elements;
std::vector<type_value_pair> m_data;
public:
using abstract_tuple::const_iterator;
object_array();
object_array(object_array&& other);
object_array(object_array const& other);
/**
* @pre
*/
void push_back(object&& what);
void push_back(object const& what);
void* mutable_at(size_t pos);
const_iterator begin() const;
const_iterator end() const;
size_t size() const;
abstract_tuple* copy() const;
......
......@@ -33,6 +33,8 @@
#include <stdexcept>
#include "cppa/type_value_pair.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -46,6 +48,9 @@ template<typename... ElementTypes>
class tuple_vals : public abstract_tuple
{
static_assert(sizeof...(ElementTypes) > 0,
"tuple_vals is not allowed to be empty");
typedef abstract_tuple super;
typedef tdata<ElementTypes...> data_type;
......@@ -56,33 +61,45 @@ class tuple_vals : public abstract_tuple
static types_array<ElementTypes...> m_types;
template<typename... Types>
void* tdata_mutable_at(tdata<Types...>& d, size_t pos)
{
return (pos == 0) ? &(d.head) : tdata_mutable_at(d.tail(), pos - 1);
}
type_value_pair m_view[sizeof...(ElementTypes)];
template<typename... Types>
void const* tdata_at(tdata<Types...> const& d, size_t pos) const
void init_view()
{
return (pos == 0) ? &(d.head) : tdata_at(d.tail(), pos - 1);
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
m_view[i].first = m_types[i];
m_view[i].second = m_data.at(i);
}
}
public:
tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { }
using abstract_tuple::const_iterator;
tuple_vals() : m_data() { }
tuple_vals() : m_data() { init_view(); }
tuple_vals(ElementTypes const&... args) : m_data(args...) { }
tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { init_view(); }
inline data_type const& data() const { return m_data; }
tuple_vals(ElementTypes const&... args) : m_data(args...) { init_view(); }
inline data_type& data_ref() { return m_data; }
inline data_type const& data() const
{
return m_data;
}
void* mutable_at(size_t pos)
inline data_type& data_ref()
{
return tdata_mutable_at(m_data, pos);
return m_data;
}
const_iterator begin() const
{
return m_view;
}
const_iterator end() const
{
return begin() + sizeof...(ElementTypes);
}
size_t size() const
......@@ -97,11 +114,20 @@ class tuple_vals : public abstract_tuple
void const* at(size_t pos) const
{
return tdata_at(m_data, pos);
CPPA_REQUIRE(pos < size());
return m_view[pos].second;
}
void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
// safe, because tuple_cals is used in cow_ptrs only
return const_cast<void*>(m_view[pos].second);
}
uniform_type_info const* type_at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_types[pos];
}
......
......@@ -73,6 +73,8 @@ class tuple
"illegal types in tuple definition: "
"pointers and references are prohibited");
friend class any_tuple;
typedef detail::tuple_vals<ElementTypes...> data_type;
cow_ptr<detail::abstract_tuple> m_vals;
......@@ -137,7 +139,6 @@ class tuple
/**
* @brief Gets the size of this tuple.
* @returns <tt>sizeof...(ElementTypes)</tt>.
*/
inline size_t size() const
{
......@@ -145,14 +146,16 @@ class tuple
}
/**
* @brief Gets a pointer to the internal data.
* @returns A const void pointer to the <tt>N</tt>th element.
* @brief Gets a const pointer to the element at position @p p.
*/
inline void const* at(size_t p) const
{
return m_vals->at(p);
}
/**
* @brief Gets a mutable pointer to the element at position @p p.
*/
inline void* mutable_at(size_t p)
{
return m_vals->mutable_at(p);
......@@ -160,26 +163,17 @@ class tuple
/**
* @brief Gets {@link uniform_type_info uniform type information}
* of an element.
* @returns The uniform type of the <tt>N</tt>th element.
* of the element at position @p p.
*/
inline uniform_type_info const* type_at(size_t p) const
{
return m_vals->type_at(p);
}
# ifdef CPPA_DOCUMENTATION
/**
* @brief Gets the internal data.
* @returns A pointer to the internal data representation.
*/
cow_ptr<InternalData> vals() const;
# else
inline cow_ptr<detail::abstract_tuple> const& vals() const
{
return m_vals;
}
# endif
};
......
......@@ -70,24 +70,24 @@ class tuple_view
typedef util::type_list<ElementTypes...> types;
static tuple_view from(std::vector< std::pair<uniform_type_info const*, void*> > const& vec)
static tuple_view from(std::vector<type_value_pair> const& vec)
{
tuple_view result;
size_t j = 0;
for (auto i = vec.begin(); i != vec.end(); ++i)
for (type_value_pair const& tvp : vec)
{
result.m_data[j++] = i->second;
result.m_data[j++] = const_cast<void*>(tvp.second);
}
return std::move(result);
}
static tuple_view from(std::vector< std::pair<uniform_type_info const*, void*> > const& vec,
static tuple_view from(std::vector<type_value_pair> const& vec,
util::fixed_vector<size_t, sizeof...(ElementTypes)> const& mv)
{
tuple_view result;
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
result.m_data[i] = vec[mv[i]].second;
result.m_data[i] = const_cast<void*>(vec[mv[i]].second);
}
return std::move(result);
}
......
......@@ -34,6 +34,8 @@
#include <algorithm>
#include <stdexcept>
#include "cppa/config.hpp"
namespace cppa { namespace util {
// @warning does not perform any bound checks
......@@ -62,7 +64,22 @@ class fixed_vector
fixed_vector(fixed_vector const& other) : m_size(other.m_size)
{
std::copy(other.m_data, other.m_data + other.m_size, m_data);
std::copy(other.begin(), other.end(), m_data);
}
void resize(size_type s)
{
CPPA_REQUIRE(s < MaxSize);
if (s > m_size)
{
auto x = T();
auto old_size = m_size;
for (auto i = old_size; i < s; ++i) push_back(x);
}
else
{
m_size = s;
}
}
inline size_type size() const
......@@ -117,12 +134,12 @@ class fixed_vector
inline iterator end()
{
return (static_cast<T*>(m_data) + m_size);
return (static_cast<iterator>(m_data) + m_size);
}
inline const_iterator end() const
{
return (static_cast<T const*>(m_data) + m_size);
return (static_cast<const_iterator>(m_data) + m_size);
}
template<class InputIterator>
......
......@@ -67,14 +67,14 @@ OUTPUT_LANGUAGE = English
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = NO
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
REPEAT_BRIEF = NO
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
......
......@@ -33,6 +33,16 @@
namespace cppa { namespace detail {
abstract_tuple::const_iterator empty_tuple::begin() const
{
return nullptr;
}
abstract_tuple::const_iterator empty_tuple::end() const
{
return nullptr;
}
size_t empty_tuple::size() const
{
return 0;
......
......@@ -49,11 +49,15 @@ object_array::object_array(object_array const& other)
void object_array::push_back(object const& what)
{
m_elements.push_back(what);
auto& back = m_elements.back();
m_data.push_back({back.type(), back.value()});
}
void object_array::push_back(object&& what)
{
m_elements.push_back(std::move(what));
auto& back = m_elements.back();
m_data.push_back({back.type(), back.value()});
}
void* object_array::mutable_at(size_t pos)
......@@ -76,6 +80,16 @@ void const* object_array::at(size_t pos) const
return m_elements[pos].value();
}
abstract_tuple::const_iterator object_array::begin() const
{
return m_data.data();
}
abstract_tuple::const_iterator object_array::end() const
{
return begin() + m_data.size();
}
bool object_array::equals(cppa::detail::abstract_tuple const& ut) const
{
if (size() == ut.size())
......
......@@ -69,6 +69,7 @@ size_t test__pattern()
pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3);
/*
auto opt = tuple_cast(i3_any_tup, i3);
CPPA_CHECK(opt.valid());
if (opt.valid())
......@@ -76,6 +77,7 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(get<0>(*opt), 1);
CPPA_CHECK_EQUAL(get<1>(*opt), 3);
}
*/
announce<foobar>(&foobar::first, &foobar::second);
......
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