|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74584 - in trunk: boost libs/foreach/test status
From: eric_at_[hidden]
Date: 2011-09-26 14:10:47
Author: eric_niebler
Date: 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
New Revision: 74584
URL: http://svn.boost.org/trac/boost/changeset/74584
Log:
support for noncopyable rvalue ranges using C++0x
Added:
trunk/libs/foreach/test/noncopyable_rvalue_const.cpp (contents, props changed)
trunk/libs/foreach/test/noncopyable_rvalue_const_r.cpp (contents, props changed)
trunk/libs/foreach/test/noncopyable_rvalue_nonconst.cpp (contents, props changed)
trunk/libs/foreach/test/noncopyable_rvalue_nonconst_r.cpp (contents, props changed)
Text files modified:
trunk/boost/foreach.hpp | 205 +++++++++++++++++++++++++++++++++++++++
trunk/libs/foreach/test/Jamfile.v2 | 6
trunk/status/explicit-failures-markup.xml | 14 ++
3 files changed, 219 insertions(+), 6 deletions(-)
Modified: trunk/boost/foreach.hpp
==============================================================================
--- trunk/boost/foreach.hpp (original)
+++ trunk/boost/foreach.hpp 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -30,8 +30,13 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
+// Some compilers support rvalue references and auto type deduction.
+// With these C++0x features, temporary collections can be bound to
+// rvalue references and their lifetime is extended. No copy/move is needed.
+#if !defined(BOOST_NO_DECLTYPE) && !defined(BOOST_NO_RVALUE_REFERENCES)
+# define BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
// Some compilers let us detect even const-qualified rvalues at compile-time
-#if !defined(BOOST_NO_RVALUE_REFERENCES) \
+#elif !defined(BOOST_NO_RVALUE_REFERENCES) \
|| BOOST_WORKAROUND(BOOST_MSVC, >= 1310) && !defined(_PREFAST_) \
|| (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \
!defined(BOOST_CLANG)) \
@@ -88,11 +93,16 @@
#include <boost/utility/addressof.hpp>
#include <boost/foreach_fwd.hpp>
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# include <boost/type_traits/decay.hpp>
+# include <boost/type_traits/remove_const.hpp>
+# include <boost/type_traits/remove_cv.hpp>
+#endif
+
#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
# include <new>
# include <boost/aligned_storage.hpp>
# include <boost/utility/enable_if.hpp>
-# include <boost/type_traits/remove_const.hpp>
#endif
namespace boost
@@ -689,6 +699,29 @@
}
#endif
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+template<typename T>
+inline typename foreach_iterator<typename remove_const<T>::type, is_const<T> >::type
+begin(T &col)
+{
+ return boost::begin(col);
+}
+
+template<typename T>
+inline T *
+begin(T *&col)
+{
+ return col;
+}
+
+template<typename T>
+inline T *
+begin(T * const &col)
+{
+ return col;
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// end
//
@@ -729,6 +762,33 @@
}
#endif
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+template<typename T>
+inline typename foreach_iterator<typename remove_const<T>::type, is_const<T> >::type
+end(T &col)
+{
+ return boost::end(col);
+}
+
+struct cstr_end_iterator
+{
+};
+
+template<typename T>
+inline cstr_end_iterator
+end(T *&col)
+{
+ return cstr_end_iterator();
+}
+
+template<typename T>
+inline cstr_end_iterator
+end(T * const &col)
+{
+ return cstr_end_iterator();
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// done
//
@@ -747,6 +807,15 @@
}
#endif
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+template<typename Iterator>
+inline bool operator !=(Iterator cur, cstr_end_iterator)
+{
+ return *cur != 0;
+}
+#endif
+
+
///////////////////////////////////////////////////////////////////////////////
// next
//
@@ -811,6 +880,35 @@
}
#endif
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+template<typename T>
+inline typename foreach_reverse_iterator<typename remove_const<T>::type, is_const<T> >::type
+rbegin(T &col)
+{
+ return boost::rbegin(col);
+}
+
+template<typename T>
+inline reverse_iterator<T *>
+rbegin(T *&col)
+{
+ T *p = col;
+ while(0 != *p)
+ ++p;
+ return reverse_iterator<T *>(p);
+}
+
+template<typename T>
+inline reverse_iterator<T *>
+rbegin(T * const &col)
+{
+ T *p = col;
+ while(0 != *p)
+ ++p;
+ return reverse_iterator<T *>(p);
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// rend
//
@@ -852,6 +950,29 @@
}
#endif
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+template<typename T>
+inline typename foreach_reverse_iterator<typename remove_const<T>::type, is_const<T> >::type
+rend(T &col)
+{
+ return boost::rend(col);
+}
+
+template<typename T>
+inline reverse_iterator<T *>
+rend(T *&col)
+{
+ return reverse_iterator<T *>(col);
+}
+
+template<typename T>
+inline reverse_iterator<T *>
+rend(T * const &col)
+{
+ return reverse_iterator<T *>(col);
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// rdone
//
@@ -922,10 +1043,40 @@
boost::foreach_detail_::to_ptr(COL) \
, boost_foreach_argument_dependent_lookup_hack_value))
-#if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION)
+///////////////////////////////////////////////////////////////////////////////
+// R-values and const R-values are bound to rvalue references
+///////////////////////////////////////////////////////////////////////////////
+#if defined(BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING)
+# define BOOST_FOREACH_PREAMBLE() \
+ BOOST_FOREACH_SUPPRESS_WARNINGS()
+
+namespace boost { namespace foreach_detail_
+{
+ template<typename T>
+ typename remove_cv<typename decay<T>::type>::type decay_copy(T &&);
+
+ template<typename T>
+ T const add_const_if_rvalue(T &&);
+}}
+# define BOOST_FOREACH_AUTO_OBJECT(NAME, EXPR) \
+ if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \
+ for (decltype(boost::foreach_detail_::decay_copy(EXPR)) NAME = (EXPR); \
+ !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true)
+
+// If EXPR is an rvalue, bind it to a const rvalue reference.
+# define BOOST_FOREACH_AUTO_REF_REF(NAME, EXPR) \
+ if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \
+ for (decltype(boost::foreach_detail_::add_const_if_rvalue(EXPR)) &&NAME = (EXPR); \
+ !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true)
+
+#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION)
///////////////////////////////////////////////////////////////////////////////
// R-values and const R-values supported here with zero runtime overhead
///////////////////////////////////////////////////////////////////////////////
+# define BOOST_FOREACH_PREAMBLE() \
+ BOOST_FOREACH_SUPPRESS_WARNINGS()
+
+
// No variable is needed to track the rvalue-ness of the collection expression
# define BOOST_FOREACH_PREAMBLE() \
@@ -1092,7 +1243,28 @@
// BOOST_FOREACH(i, int_list)
// { ... }
//
-#define BOOST_FOREACH(VAR, COL) \
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# define BOOST_FOREACH(VAR, COL) \
+ BOOST_FOREACH_PREAMBLE() \
+ BOOST_FOREACH_AUTO_REF_REF( \
+ BOOST_FOREACH_ID(_foreach_col) \
+ , COL) \
+ BOOST_FOREACH_AUTO_OBJECT( \
+ BOOST_FOREACH_ID(_foreach_cur) \
+ , boost::foreach_detail_::begin(BOOST_FOREACH_ID(_foreach_col))) \
+ BOOST_FOREACH_AUTO_OBJECT( \
+ BOOST_FOREACH_ID(_foreach_end) \
+ , boost::foreach_detail_::end(BOOST_FOREACH_ID(_foreach_col))) \
+ for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \
+ BOOST_FOREACH_ID(_foreach_continue) \
+ && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end); \
+ BOOST_FOREACH_ID(_foreach_continue) \
+ ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0) \
+ if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \
+ for (VAR = *BOOST_FOREACH_ID(_foreach_cur); \
+ !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
+#else
+# define BOOST_FOREACH(VAR, COL) \
BOOST_FOREACH_PREAMBLE() \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \
@@ -1102,6 +1274,7 @@
BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \
for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
+#endif
///////////////////////////////////////////////////////////////////////////////
// BOOST_REVERSE_FOREACH
@@ -1110,7 +1283,28 @@
// all other respects, BOOST_REVERSE_FOREACH is like
// BOOST_FOREACH.
//
-#define BOOST_REVERSE_FOREACH(VAR, COL) \
+#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# define BOOST_REVERSE_FOREACH(VAR, COL) \
+ BOOST_FOREACH_PREAMBLE() \
+ BOOST_FOREACH_AUTO_REF_REF( \
+ BOOST_FOREACH_ID(_foreach_col) \
+ , COL) \
+ BOOST_FOREACH_AUTO_OBJECT( \
+ BOOST_FOREACH_ID(_foreach_cur) \
+ , boost::foreach_detail_::rbegin(BOOST_FOREACH_ID(_foreach_col))) \
+ BOOST_FOREACH_AUTO_OBJECT( \
+ BOOST_FOREACH_ID(_foreach_end) \
+ , boost::foreach_detail_::rend(BOOST_FOREACH_ID(_foreach_col))) \
+ for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \
+ BOOST_FOREACH_ID(_foreach_continue) \
+ && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end); \
+ BOOST_FOREACH_ID(_foreach_continue) \
+ ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0) \
+ if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \
+ for (VAR = *BOOST_FOREACH_ID(_foreach_cur); \
+ !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
+#else
+# define BOOST_REVERSE_FOREACH(VAR, COL) \
BOOST_FOREACH_PREAMBLE() \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else \
@@ -1120,5 +1314,6 @@
BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \
for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
+#endif
#endif
Modified: trunk/libs/foreach/test/Jamfile.v2
==============================================================================
--- trunk/libs/foreach/test/Jamfile.v2 (original)
+++ trunk/libs/foreach/test/Jamfile.v2 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -5,7 +5,7 @@
# bring in rules for testing
import testing ;
-project : requirements <toolset>msvc:<asynch-exceptions>on ;
+project : requirements <toolset>msvc:<asynch-exceptions>on <toolset>gcc:<cxxflags>-Wconversion ;
test-suite "foreach"
: [ run stl_byval.cpp ]
@@ -32,5 +32,9 @@
[ run rvalue_nonconst_r.cpp ]
[ run dependent_type.cpp ]
[ run misc.cpp ]
+ [ run noncopyable_rvalue_const.cpp ]
+ [ run noncopyable_rvalue_nonconst.cpp ]
+ [ run noncopyable_rvalue_const_r.cpp ]
+ [ run noncopyable_rvalue_nonconst_r.cpp ]
[ compile noncopyable.cpp ]
;
Added: trunk/libs/foreach/test/noncopyable_rvalue_const.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/foreach/test/noncopyable_rvalue_const.cpp 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -0,0 +1,70 @@
+// (C) Copyright Eric Niebler 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/*
+ Revision history:
+ 25 August 2005 : Initial version.
+*/
+
+#include <boost/test/minimal.hpp>
+#include <boost/foreach.hpp>
+
+#ifndef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# error Expected failure : non-copyable rvalues disallowed
+#else
+
+class my_container
+{
+public:
+ my_container()
+ {
+ array_[0] = 1;
+ array_[1] = 2;
+ array_[2] = 3;
+ array_[3] = 4;
+ array_[4] = 5;
+ }
+
+ typedef int* iterator;
+ typedef int const* const_iterator;
+
+ iterator begin() { return array_; }
+ const_iterator begin() const { return array_; }
+
+ iterator end() { return array_ + 5; }
+ const_iterator end() const { return array_ + 5; }
+
+private:
+ int array_[5];
+
+ // non-copyable
+ my_container(my_container const &);
+ my_container &operator =(my_container const &);
+
+ // non-movable
+ my_container(my_container &&);
+ my_container &operator =(my_container &&);
+};
+
+typedef my_container const const_my_container;
+
+///////////////////////////////////////////////////////////////////////////////
+// test_main
+//
+int test_main( int, char*[] )
+{
+ int counter = 0;
+
+ BOOST_FOREACH(int i, const_my_container())
+ {
+ counter += i;
+ }
+
+ BOOST_CHECK(15 == counter);
+
+ return 0;
+}
+
+#endif
Added: trunk/libs/foreach/test/noncopyable_rvalue_const_r.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/foreach/test/noncopyable_rvalue_const_r.cpp 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -0,0 +1,70 @@
+// (C) Copyright Eric Niebler 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/*
+ Revision history:
+ 25 August 2005 : Initial version.
+*/
+
+#include <boost/test/minimal.hpp>
+#include <boost/foreach.hpp>
+
+#ifndef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# error Expected failure : non-copyable rvalues disallowed
+#else
+
+class my_container
+{
+public:
+ my_container()
+ {
+ array_[0] = 1;
+ array_[1] = 2;
+ array_[2] = 3;
+ array_[3] = 4;
+ array_[4] = 5;
+ }
+
+ typedef int* iterator;
+ typedef int const* const_iterator;
+
+ iterator begin() { return array_; }
+ const_iterator begin() const { return array_; }
+
+ iterator end() { return array_ + 5; }
+ const_iterator end() const { return array_ + 5; }
+
+private:
+ int array_[5];
+
+ // non-copyable
+ my_container(my_container const &);
+ my_container &operator =(my_container const &);
+
+ // non-movable
+ my_container(my_container &&);
+ my_container &operator =(my_container &&);
+};
+
+typedef my_container const const_my_container;
+
+///////////////////////////////////////////////////////////////////////////////
+// test_main
+//
+int test_main( int, char*[] )
+{
+ int counter = 0;
+
+ BOOST_REVERSE_FOREACH(int i, const_my_container())
+ {
+ counter += i;
+ }
+
+ BOOST_CHECK(15 == counter);
+
+ return 0;
+}
+
+#endif
Added: trunk/libs/foreach/test/noncopyable_rvalue_nonconst.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/foreach/test/noncopyable_rvalue_nonconst.cpp 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -0,0 +1,68 @@
+// (C) Copyright Eric Niebler 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/*
+ Revision history:
+ 25 August 2005 : Initial version.
+*/
+
+#include <boost/test/minimal.hpp>
+#include <boost/foreach.hpp>
+
+#ifndef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# error Expected failure : non-copyable rvalues disallowed
+#else
+
+class my_container
+{
+public:
+ my_container()
+ {
+ array_[0] = 1;
+ array_[1] = 2;
+ array_[2] = 3;
+ array_[3] = 4;
+ array_[4] = 5;
+ }
+
+ typedef int* iterator;
+ typedef int const* const_iterator;
+
+ iterator begin() { return array_; }
+ const_iterator begin() const { return array_; }
+
+ iterator end() { return array_ + 5; }
+ const_iterator end() const { return array_ + 5; }
+
+private:
+ int array_[5];
+
+ // non-copyable
+ my_container(my_container const &);
+ my_container &operator =(my_container const &);
+
+ // non-movable
+ my_container(my_container &&);
+ my_container &operator =(my_container &&);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// test_main
+//
+int test_main( int, char*[] )
+{
+ int counter = 0;
+
+ BOOST_REVERSE_FOREACH(int i, my_container())
+ {
+ counter += i;
+ }
+
+ BOOST_CHECK(15 == counter);
+
+ return 0;
+}
+
+#endif
Added: trunk/libs/foreach/test/noncopyable_rvalue_nonconst_r.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/foreach/test/noncopyable_rvalue_nonconst_r.cpp 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -0,0 +1,68 @@
+// (C) Copyright Eric Niebler 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/*
+ Revision history:
+ 25 August 2005 : Initial version.
+*/
+
+#include <boost/test/minimal.hpp>
+#include <boost/foreach.hpp>
+
+#ifndef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
+# error Expected failure : non-copyable rvalues disallowed
+#else
+
+class my_container
+{
+public:
+ my_container()
+ {
+ array_[0] = 1;
+ array_[1] = 2;
+ array_[2] = 3;
+ array_[3] = 4;
+ array_[4] = 5;
+ }
+
+ typedef int* iterator;
+ typedef int const* const_iterator;
+
+ iterator begin() { return array_; }
+ const_iterator begin() const { return array_; }
+
+ iterator end() { return array_ + 5; }
+ const_iterator end() const { return array_ + 5; }
+
+private:
+ int array_[5];
+
+ // non-copyable
+ my_container(my_container const &);
+ my_container &operator =(my_container const &);
+
+ // non-movable
+ my_container(my_container &&);
+ my_container &operator =(my_container &&);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// test_main
+//
+int test_main( int, char*[] )
+{
+ int counter = 0;
+
+ BOOST_REVERSE_FOREACH(int i, my_container())
+ {
+ counter += i;
+ }
+
+ BOOST_CHECK(15 == counter);
+
+ return 0;
+}
+
+#endif
Modified: trunk/status/explicit-failures-markup.xml
==============================================================================
--- trunk/status/explicit-failures-markup.xml (original)
+++ trunk/status/explicit-failures-markup.xml 2011-09-26 14:10:45 EDT (Mon, 26 Sep 2011)
@@ -1706,6 +1706,16 @@
ADL which these compilers do not support.
</note>
</mark-expected-failures>
+
+ <mark-expected-failures>
+ <test name="noncopyable_rvalue_const"/>
+ <test name="noncopyable_rvalue_const_r"/>
+ <test name="noncopyable_rvalue_nonconst"/>
+ <test name="noncopyable_rvalue_nonconst_r"/>
+ <toolset name="*"/>
+ <note refid="50" author="Eric Niebler"/>
+ </mark-expected-failures>
+
</library>
<!-- format -->
@@ -6695,5 +6705,9 @@
This test fails because MinGW apparently does not always catch exceptions properly.
</note>
+ <note id="50">
+ This test requires C++0x support.
+ </note>
+
</explicit-failures-markup>
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk