use the (new) iterable classification to mask for_each overloads
This commit is contained in:
parent
7d913dc558
commit
cd3a77649e
5 changed files with 119 additions and 117 deletions
|
|
@ -74,24 +74,16 @@
|
|||
#define LIB_META_DUCK_DETECTOR_H
|
||||
|
||||
|
||||
#include "lib/meta/util.hpp"
|
||||
|
||||
namespace lib {
|
||||
namespace meta{
|
||||
|
||||
|
||||
/* types for figuring out the overload resolution chosen by the compiler */
|
||||
|
||||
typedef char Yes_t;
|
||||
struct No_t { char padding[8]; };
|
||||
|
||||
////////////////////////////////////TODO: after fixing the namespace of typelist/meta programming facilities, these can be dropped.
|
||||
|
||||
|
||||
|
||||
namespace meta {
|
||||
///////////////TICKET #175 sort out meta namespace
|
||||
using lumiera::Yes_t;
|
||||
using lumiera::No_t;
|
||||
|
||||
} // namespace meta
|
||||
|
||||
} // namespace lib
|
||||
}} // namespace lib::meta
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,68 @@ namespace meta {
|
|||
|
||||
|
||||
|
||||
/** Trait template to detect a type usable with the STL for-each loop.
|
||||
* Basically we're looking for the functions to get the begin/end iterator
|
||||
*/
|
||||
template<typename T>
|
||||
class can_STL_ForEach
|
||||
{
|
||||
struct is_iterable
|
||||
{
|
||||
META_DETECT_NESTED(iterator);
|
||||
META_DETECT_FUNCTION(typename X::iterator, begin,(void));
|
||||
META_DETECT_FUNCTION(typename X::iterator, end ,(void));
|
||||
|
||||
enum { value = HasNested_iterator<T>::value
|
||||
&& HasFunSig_begin<T>::value
|
||||
&& HasFunSig_end<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
struct is_const_iterable
|
||||
{
|
||||
META_DETECT_NESTED(const_iterator);
|
||||
META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const);
|
||||
META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const);
|
||||
|
||||
enum { value = HasNested_const_iterator<T>::value
|
||||
&& HasFunSig_begin<T>::value
|
||||
&& HasFunSig_end<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
enum { value = is_iterable::value
|
||||
|| is_const_iterable::value
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** Trait template to detect a type usable immediately as
|
||||
* "Lumiera Forward Iterator" in a specialised for-each loop
|
||||
* This is just a heuristic, based on some common properties
|
||||
* of such iterators; it is enough to distinguish it from an
|
||||
* STL container, but can certainly be refined.
|
||||
*/
|
||||
template<typename T>
|
||||
class can_IterForEach
|
||||
{
|
||||
|
||||
META_DETECT_NESTED(value_type);
|
||||
META_DETECT_OPERATOR_DEREF();
|
||||
META_DETECT_OPERATOR_INC();
|
||||
|
||||
public:
|
||||
enum{ value = boost::is_convertible<T, bool>::value
|
||||
&& HasNested_value_type<T>::value
|
||||
&& HasOperator_deref<T>::value
|
||||
&& HasOperator_inc<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Type definition helper for pointer and reference types.
|
||||
* Allows to create a member field and to get the basic type
|
||||
* irrespective if the given type is plain, pointer or reference
|
||||
|
|
@ -103,7 +165,7 @@ namespace meta {
|
|||
typedef TY value_type;
|
||||
typedef lib::wrapper::AssignableRefWrapper<TY> member_type;
|
||||
};
|
||||
//////////////////////////////////////////TODO: not needed 12/09 -- obsolete? useful? keep it?
|
||||
//////////////////////////////////////////TODO: member_type not needed anymore 12/09 -- obsolete? useful? keep it?
|
||||
|
||||
|
||||
}} // namespace lib::meta
|
||||
|
|
|
|||
|
|
@ -25,53 +25,32 @@
|
|||
#define UTIL_FOREACH_H
|
||||
|
||||
#include "lib/util.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
namespace util {
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
|
||||
using lib::meta::can_STL_ForEach;
|
||||
using lib::meta::can_IterForEach;
|
||||
|
||||
/** shortcut for operating on all elements of a container.
|
||||
* Isn't this already defined somewhere? It's so obvious..
|
||||
*/
|
||||
template <typename Container, typename Oper>
|
||||
inline Oper
|
||||
for_each (Container& c, Oper doIt)
|
||||
{
|
||||
return std::for_each (c.begin(),c.end(), doIt);
|
||||
}
|
||||
|
||||
|
||||
/** All quantification: check if all elements of a collection
|
||||
* satisfy the given predicate. Actually a short-circuit
|
||||
* evaluation is performed.
|
||||
*/
|
||||
template <typename SEQ, typename Oper>
|
||||
template <typename IT, typename FUN>
|
||||
inline bool
|
||||
and_all (SEQ& coll, Oper predicate)
|
||||
and_all (IT i, IT end, FUN predicate)
|
||||
{
|
||||
typename SEQ::iterator e = coll.end();
|
||||
typename SEQ::iterator i = coll.begin();
|
||||
|
||||
for ( ; i!=e; ++i )
|
||||
if (!predicate(*i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename SEQ, typename Oper>
|
||||
inline bool
|
||||
and_all (SEQ const& coll, Oper predicate)
|
||||
{
|
||||
typename SEQ::const_iterator e = coll.end();
|
||||
typename SEQ::const_iterator i = coll.begin();
|
||||
|
||||
for ( ; i!=e; ++i )
|
||||
for ( ; i!=end; ++i )
|
||||
if (!predicate(*i))
|
||||
return false;
|
||||
|
||||
|
|
@ -83,14 +62,11 @@ namespace util {
|
|||
* of a collection satisfies the given predicate.
|
||||
* Actually, a short-circuit evaluation is performed.
|
||||
*/
|
||||
template <typename SEQ, typename Oper>
|
||||
template <typename IT, typename FUN>
|
||||
inline bool
|
||||
has_any (SEQ& coll, Oper predicate)
|
||||
has_any (IT i, IT end, FUN predicate)
|
||||
{
|
||||
typename SEQ::iterator e = coll.end();
|
||||
typename SEQ::iterator i = coll.begin();
|
||||
|
||||
for ( ; i!=e; ++i )
|
||||
for ( ; i!=end; ++i )
|
||||
if (predicate(*i))
|
||||
return true;
|
||||
|
||||
|
|
@ -98,18 +74,40 @@ namespace util {
|
|||
}
|
||||
|
||||
|
||||
template <typename SEQ, typename Oper>
|
||||
inline bool
|
||||
has_any (SEQ const& coll, Oper predicate)
|
||||
/* === specialisations for STL containers and Lumiera Forward Iterators === */
|
||||
|
||||
/** shortcut for operating on all elements of a STL container. */
|
||||
template <typename Container
|
||||
,typename FUN
|
||||
>
|
||||
inline typename disable_if< can_IterForEach<Container>,
|
||||
FUN >::type
|
||||
for_each (Container& c, FUN doIt)
|
||||
{
|
||||
typename SEQ::const_iterator e = coll.end();
|
||||
typename SEQ::const_iterator i = coll.begin();
|
||||
|
||||
for ( ; i!=e; ++i )
|
||||
if (predicate(*i))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return std::for_each (c.begin(),c.end(), doIt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Container
|
||||
,typename FUN
|
||||
>
|
||||
inline typename enable_if< can_STL_ForEach<Container>,
|
||||
bool >::type
|
||||
and_all (Container& coll, FUN predicate)
|
||||
{
|
||||
return and_all (coll.begin(),coll.end(), predicate);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container
|
||||
,typename FUN
|
||||
>
|
||||
inline typename enable_if< can_STL_ForEach<Container>,
|
||||
bool >::type
|
||||
has_any (Container& coll, FUN predicate)
|
||||
{
|
||||
return has_any (coll.begin(),coll.end(), predicate);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,59 +42,6 @@
|
|||
|
||||
|
||||
namespace lib {
|
||||
/////////////////////////////////////////////////////////////TODO draft
|
||||
|
||||
template<typename T>
|
||||
class can_STL_ForEach
|
||||
{
|
||||
struct is_iterable
|
||||
{
|
||||
META_DETECT_NESTED(iterator);
|
||||
META_DETECT_FUNCTION(typename X::iterator, begin,(void));
|
||||
META_DETECT_FUNCTION(typename X::iterator, end ,(void));
|
||||
|
||||
enum { value = HasNested_iterator<T>::value
|
||||
&& HasFunSig_begin<T>::value
|
||||
&& HasFunSig_end<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
struct is_const_iterable
|
||||
{
|
||||
META_DETECT_NESTED(const_iterator);
|
||||
META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const);
|
||||
META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const);
|
||||
|
||||
enum { value = HasNested_const_iterator<T>::value
|
||||
&& HasFunSig_begin<T>::value
|
||||
&& HasFunSig_end<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
enum { value = is_iterable::value
|
||||
|| is_const_iterable::value
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class can_IterForEach
|
||||
{
|
||||
|
||||
META_DETECT_NESTED(value_type);
|
||||
META_DETECT_OPERATOR_DEREF();
|
||||
META_DETECT_OPERATOR_INC();
|
||||
|
||||
public:
|
||||
enum{ value = boost::is_convertible<T, bool>::value
|
||||
&& HasNested_value_type<T>::value
|
||||
&& HasOperator_deref<T>::value
|
||||
&& HasOperator_inc<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////TODO draft
|
||||
namespace meta{
|
||||
namespace test{
|
||||
|
||||
|
|
|
|||
|
|
@ -216,9 +216,12 @@ namespace test{
|
|||
targets_[victim].doCount (counter_to_use);
|
||||
}
|
||||
|
||||
|
||||
typedef TargetVect::iterator iterator;
|
||||
|
||||
/** allow Iteration over all targets in the TargetVect */
|
||||
TargetVect::iterator begin() { return targets_.begin(); }
|
||||
TargetVect::iterator end() { return targets_.end(); }
|
||||
iterator begin() { return targets_.begin(); }
|
||||
iterator end() { return targets_.end(); }
|
||||
};
|
||||
|
||||
DummyTarget targetCollection;
|
||||
|
|
|
|||
Loading…
Reference in a new issue