Removed bool_testable, added note about portability of separate, explicit instantiation, changed license of documentation

[SVN r21110]
This commit is contained in:
Daniel Frey 2003-12-03 07:01:28 +00:00
parent 929517d6d7
commit 2f5945d0cd
6 changed files with 17 additions and 229 deletions

View File

@ -9,7 +9,6 @@
// See http://www.boost.org/libs/utility/operators.htm for documentation. // See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History // Revision History
// 04 May 05 Added operator class bool_testable. (Sam Partington)
// 21 Oct 02 Modified implementation of operators to allow compilers with a // 21 Oct 02 Modified implementation of operators to allow compilers with a
// correct named return value optimization (NRVO) to produce optimal // correct named return value optimization (NRVO) to produce optimal
// code. (Daniel Frey) // code. (Daniel Frey)
@ -309,20 +308,6 @@ struct indexable : B
} }
}; };
// bool_testable -----------------------------------------------------------//
// (contributed by Sam Partington, David Abrahams and Daniel Frey) ---------//
template <class T, class B = ::boost::detail::empty_base>
struct bool_testable : B
{
friend bool operator!(const T& t) { return !static_cast<bool>(t); }
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
private:
typedef signed char private_number_type;
operator private_number_type() const;
#endif
};
// More operator classes (contributed by Daryle Walker) --------------------// // More operator classes (contributed by Daryle Walker) --------------------//
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------// // (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
@ -831,8 +816,6 @@ BOOST_OPERATOR_TEMPLATE1(decrementable)
BOOST_OPERATOR_TEMPLATE2(dereferenceable) BOOST_OPERATOR_TEMPLATE2(dereferenceable)
BOOST_OPERATOR_TEMPLATE3(indexable) BOOST_OPERATOR_TEMPLATE3(indexable)
BOOST_OPERATOR_TEMPLATE1(bool_testable)
BOOST_OPERATOR_TEMPLATE(left_shiftable) BOOST_OPERATOR_TEMPLATE(left_shiftable)
BOOST_OPERATOR_TEMPLATE(right_shiftable) BOOST_OPERATOR_TEMPLATE(right_shiftable)
BOOST_OPERATOR_TEMPLATE(equivalent) BOOST_OPERATOR_TEMPLATE(equivalent)

View File

@ -72,8 +72,6 @@
<li><a href="#ordering">Ordering Note</a></li> <li><a href="#ordering">Ordering Note</a></li>
<li><a href="#symmetry">Symmetry Note</a></li> <li><a href="#symmetry">Symmetry Note</a></li>
<li><a href="#safe_bool_note">Safe-Bool Note</a></li>
</ul> </ul>
</li> </li>
@ -342,12 +340,19 @@ class MyInt
<li><code><a href="#indexable">indexable&lt;&gt;</a></code></li> <li><code><a href="#indexable">indexable&lt;&gt;</a></code></li>
<li><code><a href="#bool_testable">bool_testable&lt;&gt;</a></code></li>
<li>Any composite operator template that includes at least one of the <li>Any composite operator template that includes at least one of the
above</li> above</li>
</ul> </ul>
<p>As Daniel Kr&uuml;gler pointed out, this technique violates 14.6.5/2
and is thus non-portable. The reasoning is, that the operators injected
by the instantiation of e.g.
<code>less_than_comparable&lt;myclass&gt;</code> can not be found
by ADL according to the rules given by 3.4.2/2, since myclass is
not an associated class of
<code>less_than_comparable&lt;myclass&gt;</code>.
Thus only use this technique if all else fails.</p>
<h3>Requirement <a name="portability">Portability</a></h3> <h3>Requirement <a name="portability">Portability</a></h3>
<p>Many compilers (<i>e.g.</i> MSVC 6.3, GCC 2.95.2) will not enforce the <p>Many compilers (<i>e.g.</i> MSVC 6.3, GCC 2.95.2) will not enforce the
@ -531,17 +536,6 @@ const point&lt;float&gt; pi_over_4_normalized = pi_over_4 / length(pi_over_4);
Return convertible to <code>bool</code>.</td> Return convertible to <code>bool</code>.</td>
</tr> </tr>
<tr>
<td><code><a name="bool_testable">bool_testable&lt;T&gt;</a></code></
td>
<td><code>bool operator!(const T&)</code></td>
<td><code>static_cast&lt;bool&gt;(t)</code>.<br>
<code>T</code> convertible to <code>bool</code>. See the <a href=
"#safe_bool_note">Safe-Bool Note</a>.</td>
</tr>
<tr> <tr>
<td><code><a name="addable1">addable&lt;T&gt;</a></code><br> <td><code><a name="addable1">addable&lt;T&gt;</a></code><br>
<code>addable1&lt;T&gt;</code></td> <code>addable1&lt;T&gt;</code></td>
@ -989,132 +983,6 @@ T operator+( T lhs, const T&amp; rhs )
that don't implement the NRVO. <br> that don't implement the NRVO. <br>
<br> <br>
<h4><a name="safe_bool_note">Safe-Bool</a> Note</h4>
<p><code><a href="#bool_testable">bool_testable</a></code> provides the
antithesis of operator bool, such that the expression <code>if (!p)</code>
is valid, whilst also making <code>operator bool</code> safer by preventing
accidental conversions to integer types. If <code>operator bool</code>
were declared for a class without using
<code><a href="#bool_testable">bool_testable</code></a> then expressions
such as :</p>
<pre>
void f(int);
void g(object o)
{
f(o);
}
</pre>
<p>would compile silently, not warning the user of the (probably)
unintended behaviour of passing <code>0</code> or <code>1</code> to
<code>f()</code>.</p> <code>bool_testable&lt;&gt;</code> prevents these
accidental conversions by declaring a private conversion operator to
<code>signed char</code>, and not defining the body.</p>
<h5>Example :</h5>
<pre>
class Stream : boost::bool_testable&lt;Stream&gt;
{
public:
explicit Stream(const char * source);
operator bool() const;
// non-member bool operator!(const T&) const auto-generated and
// operator bool made safe by bool_testable&lt;&gt;
bool can_print();
};
void g(int);
void f()
{
if (Stream s1("source.txt"))
{
// use s1 ...
}
// or..
Stream s2("source.txt");
if (!s2)
{
// handle problem
}
// or ..
if (s2 && s2.can_print()) //* see <a href="#bool_testable_msvc">note</a>
{
// print something...
}
g(stream); // Will not compile, but would compile
// fine without bool_testable&lt;&gt;
}
</pre>
<h5><a name="bool_testable_msvc">Note for MSVC version 6 users</a> :</h5>
<p>Due to a bug in MSVC6, whilst compiling the above code, the compiler
will incorrectly diagnose an '<code>ambiguous operator &&</code>' at
the asterisked line. The workaround for this is to either:</p>
<pre>
if (s2)
if (s2.can_print())
</pre>
<p>or</p>
<pre>
if (!!s2 && s2.can_print())
</pre>
<p>This problem also affects the other logical operators.</p>
<h5>Rationale for Implementation</h5>
<p>Another possible implementation for <code>bool_testable</code> was the
safe-bool idiom as found in <a href=
"../smart_ptr/shared_ptr.htm#conversions"><code>shared_ptr&lt;&gt;</code>
</a> written by <a href="../../people/peter_dimov.htm">Peter Dimov</a>.
This implementation required the user to provide <code>operator!</code>,
and provided a conversion operator to a pointer to member function. This
method had the advantage of more descriptive diagnostic messages on most
platforms, when the bool conversion was used incorrectly. Unfortunately
that implementation had issues when used with a class with other user
defined integer conversion operators. This is because the integer
conversion operator provided a better match than the conversion to pointer
to member function. For example:</p>
<pre>
class MyInt : alternative_bool_testable&lt;MyInt&gt;
{
public:
bool operator!() const;
operator int() const;
// alternative_bool_testable&lt;MyInt&gt; provides :
//
// typedef void (MyInt::*member_fn)();
// operator member_fn() { return &MyInt::f; }
};
void g(int);
void f(const MyInt& i)
{
if (!i) // fine: calls operator!
...
g(i); // fine: calls operator int
if (i) // error: calls operator int NOT operator member_fn()
...
}
</pre>
<h3><a name="grpd_oprs">Grouped Arithmetic Operators</a></h3> <h3><a name="grpd_oprs">Grouped Arithmetic Operators</a></h3>
<p>The following templates provide common groups of related operations. <p>The following templates provide common groups of related operations.
@ -2203,10 +2071,6 @@ public:
<dd>Contributed the NRVO-friendly and symmetric implementation of <dd>Contributed the NRVO-friendly and symmetric implementation of
arithmetic operators.</dd> arithmetic operators.</dd>
<dt>Sam Partington</dt>
<dd>Contributed the bool_testable class.</dd>
</dl> </dl>
<h2>Note for Users of <a name="old_lib_note">Older Versions</a></h2> <h2>Note for Users of <a name="old_lib_note">Older Versions</a></h2>
@ -2255,13 +2119,15 @@ public:
backward-compatible.</p> backward-compatible.</p>
<hr> <hr>
<p>Revised: 30 Oct 2001</p> <p>Revised: 03 Dec 2003</p>
<p>Copyright &copy; David Abrahams and Beman Dawes 1999-2001. Permission <p>Copyright &copy; Beman Dawes, David Abrahams, 1999-2001.</p>
to copy, use, modify, sell and distribute this document is granted <p>Copyright &copy; Daniel Frey, 2002-2003.</p>
provided this copyright notice appears in all copies. This document is <p>Use, modification, and distribution is subject to the Boost Software
provided "as is" without express or implied warranty, and with no claim License, Version 1.0. (See accompanying file
as to its suitability for any purpose.</p> <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
</body> </body>
</html> </html>

View File

@ -6,7 +6,6 @@
// See http://www.boost.org/libs/utility for documentation. // See http://www.boost.org/libs/utility for documentation.
// Revision History // Revision History
// 23 May 03 Added tests for "bool_testable". (Sam Partington/Daniel Frey)
// 01 Oct 01 Added tests for "left" operators // 01 Oct 01 Added tests for "left" operators
// and new grouped operators. (Helmut Zeisel) // and new grouped operators. (Helmut Zeisel)
// 20 May 01 Output progress messages. Added tests for new operator // 20 May 01 Output progress messages. Added tests for new operator
@ -49,7 +48,6 @@ namespace
class Wrapped1 class Wrapped1
: boost::operators<Wrapped1<T> > : boost::operators<Wrapped1<T> >
, boost::shiftable<Wrapped1<T> > , boost::shiftable<Wrapped1<T> >
, boost::bool_testable<Wrapped1<T> >
{ {
public: public:
explicit Wrapped1( T v = T() ) : _value(v) {} explicit Wrapped1( T v = T() ) : _value(v) {}
@ -80,7 +78,6 @@ namespace
{ _value >>= x._value; return *this; } { _value >>= x._value; return *this; }
Wrapped1& operator++() { ++_value; return *this; } Wrapped1& operator++() { ++_value; return *this; }
Wrapped1& operator--() { --_value; return *this; } Wrapped1& operator--() { --_value; return *this; }
operator bool() const { return _value != 0; }
private: private:
T _value; T _value;
@ -565,13 +562,6 @@ template Wrapped6<unsigned int, unsigned char>;
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) #define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
#define PRIVATE_BOOLEAN_EXPR_TEST(t, res) BOOST_TEST(static_cast<bool>((t)) == (res))
#if defined(BOOST_MSVC)
#define PRIVATE_MSVC_BOOL_TEST_WORKAROUND(x) (!!x)
#else
#define PRIVATE_MSVC_BOOL_TEST_WORKAROUND(x) (x)
#endif
int int
test_main( int , char * [] ) test_main( int , char * [] )
{ {
@ -621,18 +611,6 @@ test_main( int , char * [] )
cout << "Created MyInt objects.\n"; cout << "Created MyInt objects.\n";
PRIVATE_BOOLEAN_EXPR_TEST( i, false );
PRIVATE_BOOLEAN_EXPR_TEST( i1, true );
PRIVATE_BOOLEAN_EXPR_TEST( i2, true );
PRIVATE_BOOLEAN_EXPR_TEST( !i, true );
PRIVATE_BOOLEAN_EXPR_TEST( !i1, false );
PRIVATE_BOOLEAN_EXPR_TEST( !i2, false );
PRIVATE_BOOLEAN_EXPR_TEST( PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i) && PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i2), false );
PRIVATE_BOOLEAN_EXPR_TEST( PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i) || PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i2), true );
PRIVATE_BOOLEAN_EXPR_TEST( PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i1) && PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i2), true );
PRIVATE_BOOLEAN_EXPR_TEST( !i && PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i2), true );
PRIVATE_BOOLEAN_EXPR_TEST( PRIVATE_MSVC_BOOL_TEST_WORKAROUND(i1) && !i, true );
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
BOOST_TEST( i2 == i ); BOOST_TEST( i2 == i );

View File

@ -1,37 +0,0 @@
// Boost safe_bool_testable test program -----------------------------------//
// (C) Copyright Daniel Frey 2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 30 Jul 03 Initial version (Daniel Frey)
#include <boost/operators.hpp>
namespace
{
struct X
: private boost::bool_testable< X >
{
operator bool() const
{
return true;
}
};
}
int main()
{
X x;
int i = x; // Should cause compile time error
i = i; // Surpress warnings which has nothing to do with the test
return 0;
} // main

View File

@ -23,7 +23,6 @@ test-suite utility
[ compile-fail ../noncopyable_test.cpp ] [ compile-fail ../noncopyable_test.cpp ]
[ run ../numeric_traits_test.cpp ] [ run ../numeric_traits_test.cpp ]
[ run ../operators_test.cpp <lib>../../test/build/boost_test_exec_monitor ] [ run ../operators_test.cpp <lib>../../test/build/boost_test_exec_monitor ]
[ compile-fail ../safe_bool_testable_test.cpp ]
[ run ../binary_search_test.cpp <lib>../../test/build/boost_test_exec_monitor ] [ run ../binary_search_test.cpp <lib>../../test/build/boost_test_exec_monitor ]
[ run ../call_traits_test.cpp : -u ] [ run ../call_traits_test.cpp : -u ]
[ compile-fail ../checked_delete_test.cpp ] [ compile-fail ../checked_delete_test.cpp ]

View File

@ -16,7 +16,6 @@ test-suite utility
[ compile-fail ../noncopyable_test.cpp ] [ compile-fail ../noncopyable_test.cpp ]
[ run ../numeric_traits_test.cpp ] [ run ../numeric_traits_test.cpp ]
[ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor ] [ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor ]
[ compile-fail ../safe_bool_testable_test.cpp ]
[ run ../binary_search_test.cpp ../../test/build//boost_test_exec_monitor ] [ run ../binary_search_test.cpp ../../test/build//boost_test_exec_monitor ]
[ run ../call_traits_test.cpp : -u ] [ run ../call_traits_test.cpp : -u ]
[ compile-fail ../checked_delete_test.cpp ] [ compile-fail ../checked_delete_test.cpp ]