use the (new) iterable classification to mask for_each overloads

This commit is contained in:
Fischlurch 2010-01-04 11:19:01 +01:00
parent 7d913dc558
commit cd3a77649e
5 changed files with 119 additions and 117 deletions

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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{

View file

@ -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;