Ticket #3996: ptr_container_propagate_noncopyable_for_foreach.patch

File ptr_container_propagate_noncopyable_for_foreach.patch, 4.2 KB (added by Kazutoshi Satoda <k_satoda@…>, 13 years ago)

The fix and test cases

  • boost/ptr_container/detail/reversible_ptr_container.hpp

     
    3535#include <boost/utility/enable_if.hpp>
    3636#include <boost/type_traits/is_pointer.hpp>
    3737#include <boost/type_traits/is_integral.hpp>
     38#include <boost/type_traits/is_same.hpp>
     39#include <boost/mpl/if.hpp>
     40#include <boost/mpl/and.hpp>
     41#include <boost/mpl/not.hpp>
     42#include <boost/noncopyable.hpp>
    3843#include <boost/swap.hpp>
    3944#include <typeinfo>
    4045#include <memory>
     
    4853namespace boost
    4954{
    5055
     56// minimum declaration required by propagate_noncopyable_for_foreach
     57namespace foreach { template< class T > struct is_noncopyable; }
     58
    5159namespace ptr_container_detail
    5260{
    5361    template< class Container >
     
    93101    struct associative_container_tag {};
    94102    struct ordered_associative_container_tag : associative_container_tag {};
    95103    struct unordered_associative_container_tag : associative_container_tag {};
    96    
    97104
     105    // Mark the ptr_container with boost::noncopyable as appropreate to
     106    // enable use of BOOST_FOREACH over const reference of ptr_container
     107    // of which value_type is noncopyable.
     108    // See: http://www.boost.org/doc/html/foreach/extensibility.html#id862475
     109    struct copyable {}; // dummy
     110    template<typename ValueType, typename CloneAllocator>
     111    struct propagate_noncopyable_for_foreach
     112      : mpl::if_<
     113          mpl::and_<
     114            mpl::not_<boost::is_same<CloneAllocator, view_clone_allocator> >,
     115            boost::foreach::is_noncopyable<ValueType>
     116          >,
     117          boost::noncopyable,
     118          copyable
     119        >::type {};
    98120   
    99121    template
    100122    <
    101123        class Config,
    102124        class CloneAllocator
    103125    >
    104     class reversible_ptr_container : CloneAllocator
     126    class reversible_ptr_container : CloneAllocator,
     127        private propagate_noncopyable_for_foreach<
     128            BOOST_DEDUCED_TYPENAME Config::value_type, CloneAllocator>
    105129    {
    106130    private:
    107131        BOOST_STATIC_CONSTANT( bool, allow_null = Config::allow_null );
  • libs/ptr_container/test/foreach_noncopyable_detection.cpp

     
     1#include "boost/ptr_container/ptr_vector.hpp"
     2#include "boost/ptr_container/ptr_map.hpp"
     3#include "boost/ptr_container/ptr_set.hpp"
     4#include "boost/foreach.hpp"
     5
     6struct normal {};
     7bool operator < (normal const&, normal const&);
     8
     9struct abstract { virtual void f() const = 0; };
     10bool operator < (abstract const&, abstract const&);
     11
     12struct noncopyable : boost::noncopyable {};
     13bool operator < (noncopyable const&, noncopyable const&);
     14
     15
     16using boost::foreach::is_noncopyable;
     17
     18template<typename T, typename CloneAllocator, bool ExpectedNoncopyable>
     19struct test_noncopyable
     20{
     21    typedef boost::ptr_vector<T, CloneAllocator> sequence;
     22    BOOST_STATIC_ASSERT(is_noncopyable<sequence>::value == ExpectedNoncopyable);
     23
     24    typedef boost::ptr_set<T, std::less<T>, CloneAllocator> set;
     25    BOOST_STATIC_ASSERT(is_noncopyable<set>::value == ExpectedNoncopyable);
     26
     27    typedef boost::ptr_map<normal, T, std::less<normal>, CloneAllocator> map;
     28    BOOST_STATIC_ASSERT(is_noncopyable<map>::value == ExpectedNoncopyable);
     29};
     30
     31
     32test_noncopyable<normal, boost::heap_clone_allocator, false>
     33normal_container_should_be_copyable;
     34
     35test_noncopyable<normal, boost::view_clone_allocator, false>
     36normal_view_should_be_copyable;
     37
     38test_noncopyable<abstract, boost::heap_clone_allocator, true>
     39abstract_container_should_be_noncopyable;
     40
     41test_noncopyable<abstract, boost::view_clone_allocator, false>
     42abstract_view_should_be_copyable;
     43
     44test_noncopyable<noncopyable, boost::heap_clone_allocator, true>
     45noncopyable_container_should_be_noncopyable;
     46
     47test_noncopyable<noncopyable, boost::view_clone_allocator, false>
     48noncopyable_view_should_be_copyable;