diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 6fe044ee8..2f934da22 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -2,6 +2,7 @@ //======================================================================= // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. // Copyright 2010 Thomas Claveirole +// Copyright (c) 2026 Arnaud Becheler // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole // // Distributed under the Boost Software License, Version 1.0. (See @@ -1217,28 +1218,24 @@ struct bidirectional_graph_helper_with_property typedef typename Config::graph_type graph_type; typedef typename Config::out_edge_iterator out_edge_iterator; - std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist( - typename Config::edge_descriptor e, const graph_type& g, void*) + // Templates so that instantiating the whole class never compiles edge_range for out edge lists that lack it. + template < class OutEdgeListS > + std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, OutEdgeListS*) { - return out_edges(source(e, g), g); - } - - std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist( - typename Config::edge_descriptor e, const graph_type& g, setS*) - { - return edge_range(source(e, g), target(e, g), g); + using has_edge_range = std::integral_constant< bool, std::is_convertible< OutEdgeListS*, setS* >::value || std::is_convertible< OutEdgeListS*, multisetS* >::value || std::is_convertible< OutEdgeListS*, hash_setS* >::value >; + return parallel_edge_sublist(e, g, has_edge_range()); } - std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist( - typename Config::edge_descriptor e, const graph_type& g, multisetS*) + template < class Graph > + std::pair< out_edge_iterator, out_edge_iterator > parallel_edge_sublist(typename Config::edge_descriptor e, const Graph& g, std::true_type) { return edge_range(source(e, g), target(e, g), g); } - std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist( - typename Config::edge_descriptor e, const graph_type& g, hash_setS*) + template < class Graph > + std::pair< out_edge_iterator, out_edge_iterator > parallel_edge_sublist(typename Config::edge_descriptor e, const Graph& g, std::false_type) { - return edge_range(source(e, g), target(e, g), g); + return out_edges(source(e, g), g); } // Placement of these overloaded remove_edge() functions diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index acb9b6bbf..4f80aadbd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,6 +49,7 @@ alias graph_test_regular : [ run betweenness_centrality_test.cpp : 100 ] [ run bidir_remove_edge.cpp ] [ compile-fail bidir_vec_remove_edge.cpp ] + [ compile bidir_list_out_edges_instantiation.cpp ] [ run bipartite_test.cpp ] [ run csr_graph_test.cpp : : : : : release ] [ run dag_longest_paths.cpp ] diff --git a/test/bidir_list_out_edges_instantiation.cpp b/test/bidir_list_out_edges_instantiation.cpp new file mode 100644 index 000000000..53e24c133 --- /dev/null +++ b/test/bidir_list_out_edges_instantiation.cpp @@ -0,0 +1,17 @@ +//======================================================================= +// Copyright (c) 2026 Arnaud Becheler +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +// Forces every member of the bidirectional helper to compile for listS out edges, as a DLL export does (issue 229). + +#include + +using EdgeProperty = boost::property< boost::edge_weight_t, double >; +using Graph = boost::adjacency_list< boost::listS, boost::listS, boost::bidirectionalS, boost::no_property, EdgeProperty >; +using Config = boost::detail::adj_list_gen< Graph, boost::listS, boost::listS, boost::bidirectionalS, boost::no_property, EdgeProperty, boost::no_property, boost::listS >::config; + +template struct boost::bidirectional_graph_helper_with_property< Config >;