Neel Basu
Neel Basu

Reputation: 12904

BGL adjacency_list<listS, listS>::vertex_descriptor evaluates to void*

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

Upvotes: 2

Views: 153

Answers (1)

sehe
sehe

Reputation: 392911

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;
}

Upvotes: 2

Related Questions