2

boost::graph_traits<graph_type>::vertex_descriptor> vertex_map_type evaluates to void* when using boost::listS for VertexListS

This following code doesn't compile. However using vecS instead of listS works.

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_serialize.hpp>

typedef boost::adjacency_list<
    boost::listS,
    boost::listS, // << ------ vecS works but listS or setS doesn't !!
    boost::bidirectionalS> graph_type;
typedef std::map<boost::uuids::uuid, typename boost::graph_traits<graph_type>::vertex_descriptor> vertex_map_type;

int main(){
    graph_type graph;
    vertex_map_type map;
    std::ofstream stream("archive");
    boost::archive::binary_oarchive archive(stream);
    archive << graph;
    archive << map;
    return 0;
}

Doesn't compile due to void*

$ g++ graph.cpp -o graph -lboost_graph -lboost_serialization
In file included from /usr/include/boost/archive/detail/interface_oarchive.hpp:23:0,
                 from /usr/include/boost/archive/detail/common_oarchive.hpp:22,
                 from /usr/include/boost/archive/basic_binary_oarchive.hpp:34,
                 from /usr/include/boost/archive/binary_oarchive_impl.hpp:23,
                 from /usr/include/boost/archive/binary_oarchive.hpp:21,
                 from graph.cpp:9:
/usr/include/boost/archive/detail/oserializer.hpp: In instantiation of ‘static void boost::archive::detail::save_pointer_type<Archive>::invoke(Archive&, TPtr) [with TPtr = void*; Archive = boost::archive::binary_oarchive]’:
/usr/include/boost/archive/detail/oserializer.hpp:525:24:   required from ‘void boost::archive::save(Archive&, T&) [with Archive = boost::archive::binary_oarchive; T = void* const]’
/usr/include/boost/archive/detail/common_oarchive.hpp:69:40:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&, int) [with T = void* const; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/basic_binary_oarchive.hpp:75:7:   required from ‘void boost::archive::basic_binary_oarchive<Archive>::save_override(const T&, int) [with T = void*; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/binary_oarchive_impl.hpp:51:9:   required from ‘void boost::archive::binary_oarchive_impl<Archive, Elem, Tr>::save_override(T&, int) [with T = void* const; Archive = boost::archive::binary_oarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:63:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = void* const; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/serialization/nvp.hpp:79:9:   [ skipping 52 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/oserializer.hpp:525:24:   required from ‘void boost::archive::save(Archive&, T&) [with Archive = boost::archive::binary_oarchive; T = const std::map<boost::uuids::uuid, void*>]’
/usr/include/boost/archive/detail/common_oarchive.hpp:69:40:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&, int) [with T = const std::map<boost::uuids::uuid, void*>; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/basic_binary_oarchive.hpp:75:7:   required from ‘void boost::archive::basic_binary_oarchive<Archive>::save_override(const T&, int) [with T = std::map<boost::uuids::uuid, void*>; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/binary_oarchive_impl.hpp:51:9:   required from ‘void boost::archive::binary_oarchive_impl<Archive, Elem, Tr>::save_override(T&, int) [with T = std::map<boost::uuids::uuid, void*>; Archive = boost::archive::binary_oarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:63:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = std::map<boost::uuids::uuid, void*>; Archive = boost::archive::binary_oarchive]’
graph.cpp:27:13:   required from here
/usr/include/boost/archive/detail/oserializer.hpp:465:27: error: ‘void*’ is not a pointer-to-object type
         register_type(ar, * t);
                           ^
/usr/include/boost/archive/detail/oserializer.hpp:473:18: error: ‘void*’ is not a pointer-to-object type
         save(ar, * t);

See it on coliru

Neel Basu
  • 12,638
  • 12
  • 82
  • 146

1 Answers1

2

That's correct. It does evaluate to the opaque integral type. This is by design and as documented.

vecS has contiguous storage, but listS and setS (etc) have iterator stability. You can pick what you need for your application.

This means you'll need an ID (BGL algorithms use the vertex_index_t property for that). Or, just use built-in serialization support.

#include <boost/archive/binary_oarchive.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_serialize.hpp>
#include <fstream>

typedef boost::adjacency_list<
    boost::listS, boost::listS, boost::bidirectionalS,
    boost::property<boost::vertex_index_t, boost::uuids::uuid>
> graph_type;

int main(){
    graph_type graph;

    std::ofstream stream("archive");
    boost::archive::binary_oarchive archive(stream);
    archive << graph;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Well I need to store a map of uuid and vertex index. So should I use `typedef std::map::vertex_descriptor> vertex_index_t;` instead ? – Neel Basu Aug 29 '15 at 11:01
  • ?! Whoa. Why would naming the typedef make a difference (I mean, c++ has obscure features, but this ain't one of them) – sehe Aug 29 '15 at 11:03
  • Added a snippet that shows what I'd consider. Of course, there's a healthy dose of [X/Y problem](http://meta.stackoverflow.com/questions/66377/what-is-the-xy-problem) now that you've discovered that indeed what you wanted to do can't be done. Regardless, even if my suggestion isn't a direct hit, you'll need to think out of the box. You simply cannot use Boost Serialization to (usefully) serialize `void*`. – sehe Aug 29 '15 at 11:06
  • sorry I thought `boost::graph_traits::vertex_index_t` will work – Neel Basu Aug 29 '15 at 11:07
  • But how will I create a `vertex_index` ? I need to `add_vertex` and store that in `std::map`. However add_vertex() returns vertex_descriptor only. – Neel Basu Aug 29 '15 at 11:09
  • That would refer to the property map itself, not what you need. It's very simple, unless `std::map` is specialized for your vertex_descriptor type, it will not know how to deal with BGL – sehe Aug 29 '15 at 11:09
  • @NeelBasu Please consider not starting many rushed question with "but" "but". It takes time to read the documentation. Does this help http://coliru.stacked-crooked.com/a/11fcd5232702f9b2 – sehe Aug 29 '15 at 11:17
  • I've also use a bidirectional map (BiMap) in some [tag:boost-graph] answers before. That would give you more efficient lookup of vertex by uuid – sehe Aug 29 '15 at 11:18
  • Well, in actual implementation I've used a `vertex_property` class instead of using `boost::property`. So how will I use `boost::vertex_index_t` with my existing `vertex_property` class ? will I just add an `uuid` property there ? I am not working on a static graph. I'll be adding/removing vertices and edges dynamically, thats why I was useing an external `map`. With `boost::property` I believe there is no need to use an external `std::map`. However is it possible to use one ? or can you provide an example that uses an external `std::map` along with the graph ? – Neel Basu Aug 29 '15 at 17:15
  • I'd be happy to look at the concrete usage pattern(s) you are trying to describe (as a new question?). These are too many questions with unclear context for me. – sehe Aug 29 '15 at 23:48
  • Yes posted http://stackoverflow.com/questions/32296206/bgl-indexing-a-vertex-by-keys – Neel Basu Aug 30 '15 at 12:01