decommission the safe-bool-idiom (closes #477)

obsoleted by C++11

 * in most cases, it can be replaced by an explicit conversion operator
 * especially for the Lumiera Forward Iterators, we need an implicit conversion
This commit is contained in:
Fischlurch 2017-04-02 06:33:56 +02:00
parent 9c21164ae6
commit afe07bdb16
36 changed files with 114 additions and 382 deletions

View file

@ -1043,7 +1043,6 @@ Items not used propagate towards the tail where they will be reused.
//access-casted.hpp
//advice.hpp symbol-impl.cpp
//allocationcluster.cpp symbol.hpp
//bool-checkable.hpp
//cmdline.cpp
//cmdline.hpp
//del-stash.hpp

View file

@ -42,7 +42,6 @@
#include "lib/error.hpp"
#include "include/logging.h"
#include "lib/bool-checkable.hpp"
#include "lib/result.hpp"
extern "C" {
@ -257,8 +256,7 @@ namespace backend {
* to join on the termination of this thread.
*/
class ThreadJoinable
: public lib::BoolCheckable<ThreadJoinable
,Thread> // baseclass
: public Thread
{
public:
ThreadJoinable (Literal purpose, Operation const& operation,

View file

@ -75,7 +75,6 @@
#define LUMIERA_QUERY_H
#include "lib/bool-checkable.hpp"
#include "lib/typed-counter.hpp"
#include "lib/iter-adapter.hpp"
#include "lib/query-text.hpp"
@ -162,7 +161,6 @@ namespace lumiera {
* @see Resolution
*/
class Result
: public lib::BoolCheckable<Result>
{
void* cur_;
@ -178,7 +176,8 @@ namespace lumiera {
}
public:
bool isValid() const { return bool(cur_); }
explicit operator bool() const { return isValid(); }
bool isValid() const { return bool(cur_); }
Result() : cur_(0) { } ///< create an NIL result
};

View file

@ -1,142 +0,0 @@
/*
BOOL-CHECKABLE.hpp - mixin template for defining a safe conversion to bool
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file bool-checkable.hpp
** Mix-in for implicit conversion to bool.
** When inheriting from BoolCheckable, a class becomes convertible
** to `bool` -- which is implemented by invoking an operation `isValid()`
** on this class.
**
** @deprecated 2016 it is not clear if we'll retain that feature on the long run.
** Essentially this was needed to work around the dangers of implicit `bool`
** conversion in C++98, which is largely obsolete since C++11, because the
** rectified semantics of implicit conversion now prevent most unexpected
** usages of this conversion function, like e.g. in comparison operators
** on a derived class. Moreover, fun fact is, the implementation in this
** header is not even correct, see Ticket #477
** On the other hand, the basic idea of exposing a `isValid()` function
** does not sound too bad...
*/
#ifndef LIB_BOOL_CHECKABLE_H
#define LIB_BOOL_CHECKABLE_H
#include <boost/static_assert.hpp>
namespace lib {
namespace imp {
struct Dummy {};
}
/**
* Provide an implicit conversion to "bool".
* Inherit (mix-in) from this template by providing the
* concrete subclass type ("CRTP"). Additionally, to implement
* the specific logic of this bool check, the subclass using this
* template must provide a public function \c isValid()
*
* \par safe bool conversion
* Generally speaking, a direct automatic conversion to bool would be
* a dangerous feature, because bool is considered an "integral type" in C.
* Thus, you'd not only get the ability to write very expressive checks
* like \c if(object) -- you would also get automatic conversions to int
* where you'd never expect them. In C++ there is a well-known idiom to
* circumvent this problem. Unfortunately, this idiom isn't easy to
* grasp, involving the convoluted syntax of member pointers.
* So we try to hide away these details into a mixin.
*
* The idea this implementation is based on is the fact that a
* pointer-to-member is "somewhat a pointer" but not \em really a pointer.
* Similar to a pointer, a member pointer can be \em unbound, and this
* is the property we exploit here. But implementation-wise, a member pointer
* is a type information plus an offset into this type, and thus can't be
* converted to an integral type. Thus, depending on the result of the
* \c isValid() function, the conversion operator returns either a
* bound or unbound member pointer.
*
* @see bool-checkable-test.cpp
* @see control::Mutation usage example
*/
template< class T ///< the target type implementing \c isValid()
, class PAR = imp::Dummy ///< optional parent for inheritance chain
>
struct BoolCheckable
: PAR
{
typedef bool (T::*ValidityCheck)() const;
typedef ValidityCheck _unspecified_bool_type;
/** implicit conversion to "bool" */
operator _unspecified_bool_type() const ///< never throws
{
ValidityCheck isValid (&T::isValid);
T const& obj = static_cast<T const&> (*this);
return (obj.*isValid)()? isValid : 0;
}
bool operator! () const ///< never throws
{
ValidityCheck isValid (&T::isValid);
T const& obj = static_cast<T const&> (*this);
return not (obj.*isValid)();
}
/** safety guard: when this comparison kicks in, the compiler
* is about to use an implicit bool conversion on both sides to
* perform an equality test. This is most likely not what you want.
* Define an explicit equality comparison in the class using BoolCheckable!
*/
friend bool
operator== (BoolCheckable const&, BoolCheckable const&)
{
BOOST_STATIC_ASSERT (false && sizeof(T) );
return false;
}
};
///////////////////////////////////////TICKET #477 : consider alternative safe-bool idiom
// struct _Hidden_type
// {
// _Hidden_type* _M_bool;
// };
//
// /// This typedef is used to implement the safe_bool idiom.
// typedef _Hidden_type* _Hidden_type::* _Safe_bool;
//
// public:
// operator _Safe_bool() const
// {
// return isValid()? &_Hidden_type::_M_bool : 0; }
} // namespace lib
#endif

View file

@ -85,7 +85,6 @@ namespace lib {
*/
template<class IT>
class PtrDerefIter
: public lib::BoolCheckable<PtrDerefIter<IT>>
{
IT i_; ///< nested source iterator
@ -142,6 +141,9 @@ namespace lib {
return *this;
}
operator bool() const { return isValid(); }
/** explicit builder to allow creating a const variant from the basic srcIter type.
* Again, the reason necessitating this "backdoor" is that we want to swallow one level
@ -230,7 +232,6 @@ namespace lib {
*/
template<class IT>
class AddressExposingIter
: public lib::BoolCheckable<AddressExposingIter<IT>>
{
typedef typename IT::pointer _Ptr;
@ -265,6 +266,7 @@ namespace lib {
takeAddress();
}
operator bool() const { return isValid(); }

View file

@ -55,7 +55,6 @@ namespace iter_stl {
*/
template<typename IT>
class DistinctIter
: public lib::BoolCheckable<DistinctIter<IT>>
{
public:
typedef typename IT::value_type value_type;
@ -72,9 +71,11 @@ namespace iter_stl {
DistinctIter() : i_(), prev_() { }
DistinctIter(IT const& i) : i_(i),prev_() { memorise(); }
pointer operator->() const { return i_; }
reference operator*() const { return *i_; }
bool isValid() const { return i_; }
pointer operator->() const { return i_; }
reference operator*() const { return *i_;}
bool isValid() const { return i_; }
operator bool() const { return i_; }
DistinctIter&
@ -415,7 +416,6 @@ namespace iter_stl {
*/
template<typename VAL>
class IterSnapshot
: public lib::BoolCheckable<IterSnapshot<VAL>>
{
typedef std::vector<VAL> Sequence;
@ -456,6 +456,8 @@ namespace iter_stl {
buffer_.push_back(*p);
}
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */

View file

@ -99,7 +99,6 @@
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/iter-type-binding.hpp"
@ -157,7 +156,6 @@ namespace lib {
*/
template<class POS, class CON>
class IterAdapter
: public lib::BoolCheckable<IterAdapter<POS,CON>>
{
CON source_;
mutable POS pos_;
@ -179,6 +177,8 @@ namespace lib {
, pos_()
{ }
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */
@ -298,7 +298,6 @@ namespace lib {
*/
template<typename T, class ST =T>
class IterStateWrapper
: public lib::BoolCheckable<IterStateWrapper<T,ST>>
{
ST core_;
@ -323,6 +322,8 @@ namespace lib {
: core_()
{ }
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */
@ -422,7 +423,6 @@ namespace lib {
*/
template<class IT>
class RangeIter
: public lib::BoolCheckable<RangeIter<IT>>
{
IT p_;
IT e_;
@ -452,6 +452,8 @@ namespace lib {
, e_(oIter.getEnd())
{ }
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */
@ -531,7 +533,6 @@ namespace lib {
*/
template<typename INT>
class NumIter
: public lib::BoolCheckable<NumIter<INT>>
{
INT i_;
INT e_;
@ -559,6 +560,8 @@ namespace lib {
// standard copy operations acceptable
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */
@ -677,7 +680,6 @@ namespace lib {
/** wrapper to declare exposed values const */
template<class IT>
class ConstIter
: public lib::BoolCheckable<ConstIter<IT>>
{
IT i_; ///< nested source iterator
@ -691,6 +693,7 @@ namespace lib {
: i_(srcIter)
{ }
operator bool() const { return isValid(); }

View file

@ -67,7 +67,6 @@
#define LIB_ITERTOOLS_H
#include "lib/bool-checkable.hpp"
#include "lib/iter-adapter.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/trait.hpp"
@ -147,7 +146,6 @@ namespace lib {
*/
template<class CORE>
class IterTool
: public lib::BoolCheckable<IterTool<CORE>>
{
protected: /* == iteration control == */
@ -167,7 +165,8 @@ namespace lib {
do core_.advance();
while (core_.pipe() && !core_.evaluate());
return core_.pipe();
return bool{core_.pipe()};
}
void
@ -191,6 +190,8 @@ namespace lib {
hasData();
}
operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */

View file

@ -57,7 +57,6 @@
#include "lib/util.hpp"
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/opaque-holder.hpp"
#include "lib/functor-util.hpp"
@ -199,7 +198,6 @@ namespace meta{
* and to retrieve it without overhead, but also without safety.
*/
class StoreUncheckedFunPtr
: public lib::BoolCheckable<StoreUncheckedFunPtr>
{
void *funP_;
@ -223,11 +221,8 @@ namespace meta{
}
bool
isValid() const
{
return funP_;
}
explicit operator bool() const { return funP_; }
bool isValid() const { return funP_; }
friend bool
operator== (StoreUncheckedFunPtr const& o1,

View file

@ -68,7 +68,6 @@
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/access-casted.hpp"
#include "lib/util.hpp"
@ -192,7 +191,6 @@ namespace lib {
///< how to access the contents via a common interface?
>
class InPlaceAnyHolder
: public BoolCheckable<InPlaceAnyHolder<siz, AccessPolicy>>
{
typedef typename AccessPolicy::Base * BaseP;
@ -475,6 +473,12 @@ namespace lib {
{
return buff().isValid();
}
explicit
operator bool() const
{
return isValid();
}
};

View file

@ -32,7 +32,6 @@
#define LIB_OPTIONAL_REF_H
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
namespace lib {
@ -60,7 +59,6 @@ namespace lib {
*/
template<typename T>
class OptionalRef
: public lib::BoolCheckable<OptionalRef<T>>
{
T* ref_;
@ -82,6 +80,9 @@ namespace lib {
: ref_(&target)
{ }
explicit operator bool() const { return isValid(); }
T&
operator() () const
{

View file

@ -146,10 +146,9 @@ namespace lib {
char content_[sizeof(TY)];
char created_;
typedef ScopedHolder<TY> _ThisType; ////TODO can get rid of this typedef, after using BoolCheckable
static char must_be_empty (_ThisType const& ref)
static char
must_be_empty (ScopedHolder<TY> const& ref)
{
if (ref)
throw lumiera::error::Logic("ScopedHolder protocol violation: "
@ -225,16 +224,9 @@ namespace lib {
}
typedef char _ThisType::*unspecified_bool_type;
//////////////////////////////////TICKET #178
/** implicit conversion to "bool" */
operator unspecified_bool_type() const // never throws
{
return created_? &_ThisType::created_ : 0;
}
bool operator! () const { return not created_; }
explicit operator bool() const { return created_; }
bool operator! () const { return not created_; }
friend void

View file

@ -34,7 +34,6 @@
#define COMMON_SEARCHPATH_H
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include <boost/noncopyable.hpp>
#include <boost/filesystem.hpp>
@ -75,8 +74,7 @@ namespace lib {
* @note #next picks the current component and advances the iteration.
*/
class SearchPathSplitter
: public BoolCheckable<SearchPathSplitter
, boost::noncopyable>
: boost::noncopyable
{
string pathSpec_;
sregex_iterator pos_,
@ -91,6 +89,8 @@ namespace lib {
, end_()
{ }
explicit operator bool() const { return isValid(); }
bool
isValid() const
{

View file

@ -42,7 +42,6 @@
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include <boost/noncopyable.hpp>
@ -57,8 +56,7 @@ namespace lib {
*/
template<class TY>
class AccessAsReference
: public lib::BoolCheckable<AccessAsReference<TY>
, boost::noncopyable>
: boost::noncopyable
{
TY* obj_;
@ -87,8 +85,8 @@ namespace lib {
return obj_;
}
bool isValid() const { return obj_; }
explicit operator bool() const { return obj_; }
bool isValid() const { return obj_; }
};
} // namespace Singleton

View file

@ -36,7 +36,6 @@
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include <boost/noncopyable.hpp>
#include <pthread.h>
@ -55,8 +54,7 @@ namespace lib {
*/
template<typename TAR>
class ThreadLocalPtr
: public BoolCheckable< ThreadLocalPtr<TAR>
, boost::noncopyable >
: boost::noncopyable
{
pthread_key_t key_;
@ -72,6 +70,8 @@ namespace lib {
WARN_IF (pthread_key_delete (key_), sync, "failure to drop thread-local data key");
}
explicit operator bool() const { return isValid(); }
bool isValid() const { return get(); }
TAR& operator* () const { return *accessChecked(); }

View file

@ -41,7 +41,6 @@
#define LIB_WRAPPER_H
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/function-closure.hpp"
#include "lib/meta/util.hpp"
@ -139,7 +138,6 @@ namespace wrapper {
*/
template<typename TY>
class ItemWrapper
: public BoolCheckable<ItemWrapper<TY>>
{
using TY_unconst = typename meta::UnConst<TY>::Type ;
@ -227,6 +225,11 @@ namespace wrapper {
return *this;
}
operator bool() const
{
return isValid();
}
/* == value access == */
TY&
@ -259,7 +262,6 @@ namespace wrapper {
*/
template<typename TY>
class ItemWrapper<TY &>
: public BoolCheckable<ItemWrapper<TY &> >
{
TY * content_;
@ -275,10 +277,12 @@ namespace wrapper {
: content_( &o )
{ }
// using default copy and assignment
/* using default copy and assignment */
operator bool() const { return isValid(); }
/** allowing to re-bind the reference */
/** allow to re-bind the reference */
ItemWrapper&
operator= (TY& otherRef)
{

View file

@ -68,7 +68,6 @@
#ifndef CONTROL_COMMAND_CLOSURE_H
#define CONTROL_COMMAND_CLOSURE_H
#include "lib/bool-checkable.hpp"
#include "lib/meta/function-erasure.hpp"
#include "proc/control/argument-erasure.hpp"
#include "lib/diff/gen-node.hpp"
@ -105,10 +104,10 @@ namespace control {
/** Interface */
class CmdClosure
: public lib::BoolCheckable<CmdClosure>
{
public:
virtual ~CmdClosure() {}
explicit operator bool() const { return isValid(); }
virtual operator string() const =0;
virtual bool isValid () const =0; ///< does this closure hold a valid argument tuple?

View file

@ -62,7 +62,6 @@
#include "proc/control/command-signature.hpp"
#include "proc/control/command-mutation.hpp"
#include "proc/control/argument-tuple-accept.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp"
@ -260,7 +259,7 @@ namespace control {
/**
* Helper class used solely for \em defining a Command-Object.
* Helper class used solely for _defining_ a Command-Object.
* This technique is known as "fluent API", see http://en.wikipedia.org/wiki/Fluent_interface
* The basic idea is for the user to create a disposable instance of this definition helper,
* only for calling a chain of definition functions, which internally build the actual Command object.
@ -277,8 +276,7 @@ namespace control {
*
*/
class CommandDef
: public lib::BoolCheckable<CommandDef
, boost::noncopyable >
: boost::noncopyable
{
Symbol id_;
Command prototype_;
@ -311,6 +309,8 @@ namespace control {
}
explicit operator bool() const { return isValid(); }
bool isValid() const;

View file

@ -45,7 +45,6 @@
#include "proc/control/command.hpp"
#include "proc/control/command-closure.hpp"
#include "proc/control/command-mutation.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/format-string.hpp"
#include <boost/noncopyable.hpp>
@ -78,9 +77,7 @@ namespace control {
* @see Mutation
*/
class CommandImpl
: public lib::BoolCheckable<CommandImpl
, boost::noncopyable
>
: boost::noncopyable
{
Mutation do_;
UndoMutation undo_;
@ -146,6 +143,8 @@ namespace control {
, defaultPatt_(orig.defaultPatt_)
{ }
explicit operator bool() const { return isValid(); }
/** assist with building a clone copy of this CommandImpl.
* By accepting the clone builder as a visitor and dispatching

View file

@ -46,7 +46,6 @@
#define CONTROL_COMMAND_MUTATION_H
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "proc/control/command-closure.hpp"
#include "proc/control/memento-tie.hpp"

View file

@ -36,7 +36,6 @@
#ifndef CONTROL_COMMAND_OP_CLOSURE_H
#define CONTROL_COMMAND_OP_CLOSURE_H
#include "lib/bool-checkable.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/function-closure.hpp"
#include "lib/meta/tuple-helper.hpp"

View file

@ -59,7 +59,6 @@
#include "proc/control/argument-tuple-accept.hpp"
#include "proc/control/handling-pattern.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/diff/gen-node.hpp"
#include "lib/handle.hpp"

View file

@ -46,7 +46,6 @@
#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "lib/bool-checkable.hpp"
#include <string>
@ -70,13 +69,13 @@ namespace control {
* @todo couldn't that be replaced by a lib::Result<void> instance??
*/
class ExecResult
: public lib::BoolCheckable<ExecResult>
{
const string log_;
public:
bool isValid() const;
void maybeThrow() const;
operator bool() const { return isValid(); }
protected:
ExecResult () { } ///< default: command executed successfully
@ -95,7 +94,6 @@ namespace control {
* asynchronously in a background thread.
*/
class HandlingPattern
: public lib::BoolCheckable<HandlingPattern>
{
public:
virtual ~HandlingPattern() {} ///< this is an interface
@ -125,8 +123,8 @@ namespace control {
/** likewise invoke the configured UNDO operation */
ExecResult undo (CommandImpl& command, string) const;
virtual bool isValid() const =0;
explicit operator bool() const { return isValid(); }
virtual bool isValid() const =0;
protected:

View file

@ -40,7 +40,6 @@
#ifndef CONTROL_MEMENTO_TIE_H
#define CONTROL_MEMENTO_TIE_H
#include "lib/bool-checkable.hpp"
#include "lib/meta/maybe-compare.hpp"
#include "lib/meta/function-closure.hpp"
#include "proc/control/command-signature.hpp"
@ -89,9 +88,7 @@ namespace control {
*/
template<typename SIG, typename MEM>
class MementoTie
: public lib::BoolCheckable<MementoTie<SIG,MEM>,
equality_comparable<MementoTie<SIG,MEM>
> >
: public equality_comparable<MementoTie<SIG,MEM>>
{
typedef typename CommandSignature<SIG,MEM>::CaptureSig SIG_cap;
typedef typename CommandSignature<SIG,MEM>::UndoOp_Sig SIG_undo;
@ -180,6 +177,12 @@ namespace control {
* if all functions are usable and
* memento state has been captured
*/
explicit
operator bool() const
{
return isValid();
}
bool
isValid () const
{

View file

@ -54,7 +54,6 @@
#include "lib/error.hpp"
#include "lib/hash-value.h"
#include "proc/streamtype.hpp"
#include "lib/bool-checkable.hpp"
namespace proc {
@ -110,7 +109,6 @@ namespace engine {
* The real buffer pointer can be retrieved by dereferencing this smart-handle class.
*/
class BuffHandle
: public lib::BoolCheckable<BuffHandle>
{
typedef StreamType::ImplFacade::DataBuffer Buff;
@ -130,6 +128,7 @@ namespace engine {
// using standard copy operations
explicit operator bool() const { return isValid(); }
void emit();

View file

@ -39,7 +39,6 @@
#include "lib/error.hpp"
#include "lib/hash-value.h"
#include "proc/streamtype.hpp"
#include "lib/bool-checkable.hpp"
namespace proc {

View file

@ -29,7 +29,6 @@
#include "lib/error.hpp"
#include "include/logging.h"
//#include "lib/meta/function.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/scoped-ptrvect.hpp"
#include "lib/scoped-holder.hpp"
#include "lib/util-foreach.hpp"
@ -106,7 +105,6 @@ namespace engine {
* later investigation and diagnostics.
*/
class BlockPool
: public lib::BoolCheckable<BlockPool>
{
uint maxAllocCount_;
size_t memBlockSize_;
@ -180,7 +178,13 @@ namespace engine {
bool
isValid() const
{
return blockList_;
return bool(blockList_);
}
explicit
operator bool() const
{
return isValid();
}
private:

View file

@ -67,7 +67,6 @@
#define PROC_MOBJECT_MODEL_PORT_H
#include "proc/asset/pipe.hpp"
#include "lib/bool-checkable.hpp"
#include "proc/streamtype.hpp"
namespace proc {
@ -103,7 +102,6 @@ namespace mobject {
* @see ModelPortRegistry_test abstract usage example
*/
class ModelPort
: public lib::BoolCheckable<ModelPort>
{
ID<asset::Pipe> id_;
@ -129,6 +127,12 @@ namespace mobject {
return exists (this->id_);
}
explicit
operator bool() const
{
return isValid();
}
friend bool
operator== (ModelPort const& mp1, ModelPort const& mp2)

View file

@ -56,7 +56,6 @@
#include "lib/util.hpp"
#include "lib/hash-value.h"
#include "proc/asset/pipe.hpp"
#include "lib/bool-checkable.hpp"
#include "common/query.hpp"
#include <boost/operators.hpp>
@ -159,10 +158,8 @@ namespace mobject {
* @note depends on the template parameter of the enclosing OutputMapping type!
*/
class Resolver
: public lib::BoolCheckable<Resolver // bool conversion to signal "unconnected"...
, boost::equality_comparable<Resolver, Target, // final mapping result can be compared to Target...
boost::equality_comparable<Resolver> // mapping values can be compared.
> > //
: public boost::equality_comparable<Resolver, Target // final mapping result can be compared to Target...
, boost::equality_comparable<Resolver>> // mapping values can be compared.
{
OutputMapping& thisMapping_;
HashVal& pID_;
@ -230,6 +227,12 @@ namespace mobject {
return bool(pID_);
}
explicit
operator bool() const
{
return isValid();
}
/* === equality comparisons (boost::operators) === */

View file

@ -66,7 +66,6 @@
#define MOBJECT_PLACEMENT_REF_H
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "proc/mobject/placement.hpp"
#include "proc/mobject/explicitplacement.hpp" /////////////TODO this is ugly! Why can't placement::resolve() return a reference??
#include "proc/mobject/session/session-service-fetch.hpp"
@ -98,7 +97,6 @@ namespace proc {
*/
template<class MX =MObject>
class PlacementRef
: public lib::BoolCheckable<PlacementRef<MX>>
{
typedef Placement<MX> PlacementMX;
typedef Placement<MObject>::ID _ID;
@ -206,6 +204,12 @@ namespace proc {
/* == forwarding part of the Placement-API == */
explicit
operator bool() const
{
return isValid();
}
bool isValid() const
{
if (checkValidity())

View file

@ -88,7 +88,6 @@
#define PROC_MOBJECT_SESSION_SCOPE_PATH_H
#include "proc/mobject/session/scope.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/iter-adapter.hpp"
#include "lib/error.hpp"
@ -137,7 +136,6 @@ namespace session {
* and QueryFocus to establish the \em current focus (path).
*/
class ScopePath
: public lib::BoolCheckable<ScopePath>
{
size_t refcount_;
std::vector<Scope> path_;
@ -157,6 +155,8 @@ namespace session {
static const ScopePath INVALID;
explicit operator bool() const { return isValid(); }
/* == state diagnostics == */
bool isValid() const;

View file

@ -2,27 +2,6 @@ TESTING "Metaprogramming facilities and techniques" ./test-suite --group=common
TEST "implicit conversion to bool" BoolCheckable_test <<END
out: 1
out: 2
out: doIt
out: 4
out: 5
out: doIt
out: 7
out: 8
out: doIt
out: 10
out: 11
out: doIt
out: 13
out: 14
out: doIt
out: sizeof. ExampleCustomType123 . = [248]
return: 0
END
TEST "ConfigFlags_test" ConfigFlags_test <<END
out-lit: Conf0 :-
out-lit: Conf1 :-<1>-

View file

@ -142,12 +142,12 @@ namespace test{
, bind (&HavocThread::doIt, this)
)
{
CHECK (thread_);
CHECK (thread_.isValid());
}
~HavocThread ()
{
if (thread_)
if (thread_.isValid())
thread_.join();
}
};

View file

@ -161,8 +161,8 @@ namespace test{
Thread ping ("SyncWaiting ping", bind (&Token::getIt, &tok));
Thread pong ("SyncWaiting pong", bind (&Token::getIt, &tok));
CHECK (ping);
CHECK (pong);
CHECK (ping.isValid());
CHECK (pong.isValid());
CHECK (0 == tok.result());
usleep (100000); // if the threads don't block correctly, they've missed their chance by now...

View file

@ -1,109 +0,0 @@
/*
BoolCheckable(Test) - verify the mixin for implicit conversion to bool
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file bool-checkable-test.cpp
** unit test \ref BoolCheckable_test
*/
#include "lib/test/run.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/test/test-helper.hpp"
#include <iostream>
using std::cout;
using lib::test::showSizeof;
namespace lib {
namespace test{
/**
* An example custom type,
* which provides an implicit bool conversion
* to express some special validity check.
*/
class ExampleCustomType123
: public lib::BoolCheckable<ExampleCustomType123>
{
int val_;
public:
ExampleCustomType123 (int i)
: val_(i)
{ }
/** implements the custom logic to decide
* if this instance can be considered "valid"
*/
bool
isValid() const
{
return val_ % 3;
}
};
/******************************************************//**
* @test verify the implementation of a validity check,
* to be accessed as an implicit conversion to bool.
*
* @see lib::BoolCheckable
* @todo list some usage examples here
*/
class BoolCheckable_test : public Test
{
virtual void
run (Arg)
{
for (int i=1; i<16; ++i)
{
ExampleCustomType123 test (i);
if (!test)
cout << "doIt \n";
if (test)
cout << i << "\n";
CHECK (test.isValid() == bool(test) );
CHECK (test.isValid() != !test);
}
cout << showSizeof<ExampleCustomType123>() <<"\n";
CHECK (sizeof (int) == sizeof (ExampleCustomType123));
}
};
/** Register this test class... */
LAUNCHER (BoolCheckable_test, "unit common");
}} // namespace lib::test

View file

@ -30,9 +30,7 @@
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/util-foreach.hpp"
#include "lib/opaque-holder.hpp"
#include "lib/bool-checkable.hpp"
#include <iostream>
#include <vector>
@ -81,7 +79,6 @@ namespace test{
struct Special
: DD<7>
, BoolCheckable<Special>
{
ulong myVal_;
@ -89,8 +86,8 @@ namespace test{
: myVal_(val)
{ }
bool
isValid () const ///< custom boolean "validity" check
explicit
operator bool() const ///< custom boolean "validity" check
{
return myVal_ % 2;
}