Opened 8 years ago

Last modified 8 years ago

#10540 new Bugs

missing std::nullptr_t support in boost/type_traits/is_pointer.hpp

Reported by: Stephan Bergmann <sbergman@…> Owned by: Thorsten Ottosen
Milestone: To Be Determined Component: ptr_container
Version: Boost 1.56.0 Severity: Problem
Keywords: Cc:

Description

...leads to a failures when inserting a nullptr into a boost::ptr_vector:

$ cat test.cc
#include "boost/ptr_container/nullable.hpp"
#include "boost/ptr_container/ptr_vector.hpp"
void f(boost::ptr_vector<boost::nullable<int>> & v) {
    v.insert(v.begin(), nullptr);
}

$ g++ -std=c++11 -c test.cc
In file included from .../boost_1_56_0/boost/ptr_container/nullable.hpp:21:0,
                 from test.cc:1:
.../boost_1_56_0/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if_c<true, boost::range_const_iterator<std::nullptr_t, void>, boost::range_mutable_iterator<std::nullptr_t, void> >’:
.../boost_1_56_0/boost/range/iterator.hpp:69:17:   required from ‘struct boost::range_iterator<std::nullptr_t, void>’
.../boost_1_56_0/boost/range/begin.hpp:106:61:   required by substitution of ‘template<class T> typename boost::range_iterator<const T>::type boost::range_adl_barrier::begin(const T&) [with T = std::nullptr_t]’
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:421:43:   required from ‘typename boost::disable_if<boost::ptr_container_detail::is_pointer_or_integral<Range> >::type boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::insert(boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::iterator, const Range&) [with Range = std::nullptr_t; T = boost::nullable<int>; VoidPtrSeq = std::vector<void*, std::allocator<void*> >; CloneAllocator = boost::heap_clone_allocator; typename boost::disable_if<boost::ptr_container_detail::is_pointer_or_integral<Range> >::type = void; boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::iterator = boost::void_ptr_iterator<__gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, int>]’
test.cc:4:32:   required from here
.../boost_1_56_0/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<std::nullptr_t, void>, boost::range_mutable_iterator<std::nullptr_t, void> >::f_ {aka struct boost::range_const_iterator<std::nullptr_t, void>}’
     typedef typename f_::type type;
                               ^
In file included from .../boost_1_56_0/boost/ptr_container/ptr_vector.hpp:20:0,
                 from test.cc:2:
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp: In instantiation of ‘typename boost::disable_if<boost::ptr_container_detail::is_pointer_or_integral<Range> >::type boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::insert(boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::iterator, const Range&) [with Range = std::nullptr_t; T = boost::nullable<int>; VoidPtrSeq = std::vector<void*, std::allocator<void*> >; CloneAllocator = boost::heap_clone_allocator; typename boost::disable_if<boost::ptr_container_detail::is_pointer_or_integral<Range> >::type = void; boost::ptr_sequence_adapter<T, VoidPtrSeq, CloneAllocator>::iterator = boost::void_ptr_iterator<__gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, int>]’:
test.cc:4:32:   required from here
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:421:43: error: no matching function for call to ‘begin(std::nullptr_t&)’
             insert( before, boost::begin(r), boost::end(r) );
                                           ^
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:421:43: note: candidates are:
In file included from .../boost_1_56_0/boost/range/functions.hpp:18:0,
                 from .../boost_1_56_0/boost/ptr_container/detail/reversible_ptr_container.hpp:29,
                 from .../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:20,
                 from .../boost_1_56_0/boost/ptr_container/ptr_vector.hpp:20,
                 from test.cc:2:
.../boost_1_56_0/boost/range/begin.hpp:97:55: note: template<class T> typename boost::range_iterator<C>::type boost::range_adl_barrier::begin(T&)
 inline BOOST_DEDUCED_TYPENAME range_iterator<T>::type begin( T& r )
                                                       ^
.../boost_1_56_0/boost/range/begin.hpp:97:55: note:   template argument deduction/substitution failed:
.../boost_1_56_0/boost/range/begin.hpp:106:61: note: template<class T> typename boost::range_iterator<const T>::type boost::range_adl_barrier::begin(const T&)
 inline BOOST_DEDUCED_TYPENAME range_iterator<const T>::type begin( const T& r )
                                                             ^
.../boost_1_56_0/boost/range/begin.hpp:106:61: note:   substitution of deduced template arguments resulted in errors seen above
In file included from .../boost_1_56_0/boost/ptr_container/ptr_vector.hpp:20:0,
                 from test.cc:2:
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:421:58: error: no matching function for call to ‘end(std::nullptr_t&)’
             insert( before, boost::begin(r), boost::end(r) );
                                                          ^
.../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:421:58: note: candidates are:
In file included from .../boost_1_56_0/boost/range/functions.hpp:19:0,
                 from .../boost_1_56_0/boost/ptr_container/detail/reversible_ptr_container.hpp:29,
                 from .../boost_1_56_0/boost/ptr_container/ptr_sequence_adapter.hpp:20,
                 from .../boost_1_56_0/boost/ptr_container/ptr_vector.hpp:20,
                 from test.cc:2:
.../boost_1_56_0/boost/range/end.hpp:91:55: note: template<class T> typename boost::range_iterator<C>::type boost::range_adl_barrier::end(T&)
 inline BOOST_DEDUCED_TYPENAME range_iterator<T>::type end( T& r )
                                                       ^
.../boost_1_56_0/boost/range/end.hpp:91:55: note:   template argument deduction/substitution failed:
.../boost_1_56_0/boost/range/end.hpp:100:61: note: template<class T> typename boost::range_iterator<const T>::type boost::range_adl_barrier::end(const T&)
 inline BOOST_DEDUCED_TYPENAME range_iterator<const T>::type end( const T& r )
                                                             ^
.../boost_1_56_0/boost/range/end.hpp:100:61: note:   template argument deduction/substitution failed:

What would fix this is:

--- boost/type_traits/is_pointer.hpp	2014-07-09 20:04:22.000000000 +0200
+++ boost/type_traits/is_pointer.hpp	2014-09-25 15:37:45.895757102 +0200
@@ -72,6 +72,10 @@
 
 BOOST_TT_AUX_BOOL_TRAIT_DEF1(is_pointer,T,::boost::detail::is_pointer_impl<T>::value)
 
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+BOOST_TT_AUX_BOOL_TRAIT_SPEC1(is_pointer,::std::nullptr_t,true)
+#endif
+
 #if defined(__BORLANDC__) && !defined(__COMO__) && (__BORLANDC__ < 0x600)
 BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC1_1(typename T,is_pointer,T&,false)
 BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC1_1(typename T,is_pointer,T& const,false)

Change History (2)

comment:1 by John Maddock, 8 years ago

Component: type_traitsptr_container
Owner: changed from John Maddock to Thorsten Ottosen

That's not the right fix - std::nullptr_t is not a pointer type - it's a type that's convertible to a pointer which is a whole other ball game.

I believe the correct fix is for ptr_container to provide an explicit overload for std::nullptr_t for methods like insert. Reassigning in case someone wants to apply a fix there.

in reply to:  1 comment:2 by Stephan Bergmann <sbergman@…>, 8 years ago

Replying to johnmaddock:

That's not the right fix - std::nullptr_t is not a pointer type - it's a type that's convertible to a pointer which is a whole other ball game.

Ach, right. My bad.

Note: See TracTickets for help on using tickets.