Opened 8 years ago

Last modified 8 years ago

#10382 new Bugs

1.56.0 Graph adjacency_list has compile errors on g++ 4.6.4

Reported by: Conrad Mercer <conrad.mercer@…> Owned by: Jeremiah Willcock
Milestone: To Be Determined Component: graph
Version: Boost 1.56.0 Severity: Showstopper
Keywords: compile error Cc:

Description

The following code will generate compile errors on g++ 4.6.4 but works on g++ 4.7 and 4.8. The problem looks to be in detail/adjacency_list.hpp:319-21 where the = default; specification is unable to generate a valid implementation so the move operators become implicitly deleted.

#include "boost/graph/adjacency_list.hpp"

int main(int argc, char** argv)
{
  using boost::adjacency_list;
  using boost::vecS;
  using boost::directedS;
  typedef adjacency_list<vecS, vecS, directedS, boost::default_color_type> Graph;

  std::vector< std::pair<int, int> > testVec;
  auto graph = Graph( begin(testVec), end(testVec), testVec.size());

  return 0;
}

Attachments (4)

adjacency_list.hpp (105.4 KB ) - added by Conrad Mercer <conrad.mercer@…> 8 years ago.
Attached a patched version of adjacency_list.hpp that resolves the compile errors
boost_bug10382.patch (1.1 KB ) - added by mikael.s.persson@… 8 years ago.
Patch on stored_edge class for bug10382
adjacency_list.2.hpp (105.3 KB ) - added by phreakuencies@… 8 years ago.
original archlinux adjacency_list.hpp
adjacency_list_fixed.hpp (105.2 KB ) - added by phreakuencies@… 8 years ago.
adjacency list fixed for 4.9

Download all attachments as: .zip

Change History (12)

by Conrad Mercer <conrad.mercer@…>, 8 years ago

Attachment: adjacency_list.hpp added

Attached a patched version of adjacency_list.hpp that resolves the compile errors

comment:1 by Conrad Mercer <conrad.mercer@…>, 8 years ago

Figured the precise cause of this, as detailed here: http://stackoverflow.com/questions/25395805/compile-error-with-boost-graph-1-56-0-and-g-4-6-4. The problem is that stored_edge is the base of stored_edge_property and it doesn't define move operators preventing stored_edge_property from doing so when it tries to.

comment:2 by Conrad Mercer <conrad.mercer@…>, 8 years ago

Just a quick clarification for the uploaded adjacency_list.hpp; it demonstrates how the problem can be resolved but is not correctly switched for compiler versions etc

comment:3 by mikael.s.persson@…, 8 years ago

Here is a git-diff style patch for this.

For the switching for compiler versions, I just assumed the three cases covered in the stored_edge_property class, that is: no rvalue support (legacy code); rvalue and defaulting support (defaulted move functions); and, the "msvc" exception for quirky defaulting behavior. In the legacy version, no additional code is required in stored_edge. In the "msvc" exception, there is also nothing required because the move functions in stored_edge_property rely on the copy functions of stored_edge (which is fine if "Vertex" is a POD-type, which is the case for all adj-list variations). So, the only real code is the default move functions added for that case when rvalue and defaulting is well supported.

I also added a defaulted copy-constructor for stored_edge. This is because stored_edge is copyable in all other cases (and providing a move-constructor disables the implicit copy-constructor), and therefore, should remain so to minimize the chance of any other collateral damage elsewhere.

by mikael.s.persson@…, 8 years ago

Attachment: boost_bug10382.patch added

Patch on stored_edge class for bug10382

comment:4 by mhassert@…, 8 years ago

Mikael, thanks for the patch!

But I think there's a small typo in there. Instead of

    #if !(defined(BOOST_MSVC) || (defined(BOOST_GCC) || (BOOST_GCC / 100) < 406))

it should read

    #if !(defined(BOOST_MSVC) || (defined(BOOST_GCC) && (BOOST_GCC / 100) < 406))

That is, "&&" instead of "||".

in reply to:  4 comment:5 by anonymous, 8 years ago

Replying to mhassert@…:

Yes I had noticed that typo before, I had it fixed in the pending pull request that I issued:

github <dot> com / boostorg / graph / pull / 18

Hopefully it will be merged eventually....

comment:6 by phreakuencies@…, 8 years ago

Hi, I'm using gcc 4.9 (on archlinux) and had this bug (complained about deleted operator on stored_edge_property), which appeared when using adjacency_list with listS/vecS. I added this patch and it did not change the behavior (bug still appears). I noticed it is only enabled on a specific version of GCC and thus I removed that condition but it made no difference. I looked into the .hpp file (unpatched) and noticed there was a similar condition for stored_edge_property, which now looks like this and the bug disappeared (changed first line of this code):

#if defined(BOOST_MSVC) || (defined(BOOST_GCC))
      stored_edge_property(self&& x) : Base(static_cast< Base const& >(x)) {
        m_property.swap(x.m_property);
      }
      stored_edge_property(self const& x) : Base(static_cast< Base const& >(x)) {
        m_property.swap(const_cast<self&>(x).m_property);
      }
      self& operator=(self&& x) {
        Base::operator=(static_cast< Base const& >(x));
        m_property = std::move(x.m_property);
        return *this;
      }
      self& operator=(self const& x) {
        Base::operator=(static_cast< Base const& >(x));
        m_property = std::move(const_cast<self&>(x).m_property);
        return *this;
      }

comment:7 by mikael.s.persson@…, 8 years ago

@phreakuencies: Did you make sure to make the correction that mhassert posted 11 days ago (which also had on my pull request)? The thing is that the special code, that is conditionally applied there, is not suppose to cause problems with later versions of GCC (otherwise, several other parts of Boost would break too!). It would be useful to see the actual errors you are getting with this, in addition to the state of the code (stored_edge_property and stored_edge) that corresponds to that error.

I'm not sure what's causing this issue for GCC 4.9. But in light of this, I would recommend that the whole thing be simplified. I think the original idea was to use the implicit default operators / constructors whenever possible (to keep the class "trivial", in the standard sense). But compilers have had a rocky history with defaulting and implicitly deleting operators / constructors, so it might be easier to just abandon the idea altogether. But of course, this is a decision for the maintainer (Jeremiah), which seems to have fallen off the grid for several months now.

by phreakuencies@…, 8 years ago

Attachment: adjacency_list.2.hpp added

original archlinux adjacency_list.hpp

by phreakuencies@…, 8 years ago

Attachment: adjacency_list_fixed.hpp added

adjacency list fixed for 4.9

comment:8 by phreakuencies@…, 8 years ago

Hi, yes, I changed the "or" to "and". The fix proposed here is not the problem. I applied the patch first and did not change behavior. I had the "deleted operator" message. I looked at the file, and realized there was already a conditional code which (as I understand) was only enabled for previous compilers. Once I re-enabled that, it started working.

Here's the error produced (attach original and modified files):

In file included from /usr/include/c++/4.9.1/memory:64:0,
                 from /usr/include/boost/config/no_tr1/memory.hpp:21,
                 from /usr/include/boost/smart_ptr/shared_ptr.hpp:23,
                 from /usr/include/boost/shared_ptr.hpp:17,
                 from /usr/include/boost/property_map/vector_property_map.hpp:14,
                 from /usr/include/boost/property_map/property_map.hpp:600,
                 from /home/v01d/coding/ros/src/surfnav/src/lib/map.cpp:1:
/usr/include/c++/4.9.1/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >; _Args = {const boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >&}]’:
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:75:53:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*, std::vector<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >, std::allocator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > > > > >; _ForwardIterator = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:125:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*, std::vector<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >, std::allocator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > > > > >; _ForwardIterator = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*]’
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:278:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*, std::vector<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >, std::allocator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > > > > >; _ForwardIterator = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >*; _Tp = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >]’
/usr/include/c++/4.9.1/bits/stl_vector.h:324:32:   required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >; _Alloc = std::allocator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > > >]’
/usr/include/boost/graph/detail/adjacency_list.hpp:2399:16:   required from ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex; _Args = {boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex&}]’
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:75:53:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:278:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex*; _ForwardIterator = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex*; _Tp = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex]’
/usr/include/c++/4.9.1/bits/stl_uninitialized.h:301:67:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex*; _ForwardIterator = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex*; _Allocator = std::allocator<boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex>]’
/usr/include/c++/4.9.1/bits/vector.tcc:564:42:   required from ‘void std::vector<_Tp, _Alloc>::_M_default_append(std::vector<_Tp, _Alloc>::size_type) [with _Tp = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex; _Alloc = std::allocator<boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/4.9.1/bits/stl_vector.h:676:41:   required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex; _Alloc = std::allocator<boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config::stored_vertex>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/boost/graph/detail/adjacency_list.hpp:2192:7:   required from ‘typename Config::vertex_descriptor boost::add_vertex(boost::vec_adj_list_impl<G, C, B>&) [with Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>; Config = boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config; Base = boost::directed_graph_helper<boost::detail::adj_list_gen<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>, boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, long unsigned int, surfnav::Node>, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> >, boost::no_property, boost::vecS>::config>; typename Config::vertex_descriptor = long unsigned int]’
/home/v01d/coding/ros/src/surfnav/src/lib/map.cpp:13:36:   required from here
/usr/include/c++/4.9.1/bits/stl_construct.h:75:7: error: use of deleted function ‘boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >::stored_edge_property(const boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_index_t, long unsigned int, boost::shared_ptr<surfnav::Segment> > >&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
Note: See TracTickets for help on using tickets.