I have some code that can handle different types of (boost)graphs, and I want to do something special for graphs having some specific bundle property.
For example, this:
struct VertexProp
{
// some data
};
My code can use two types of graphs:
using graph1_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
VertexProp
> ;
or
using graph2_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS
> ;
My intent is to use SFINAE to enable a function that will only handle this specific case:
template<Graph_t>
void foo
(
const Graph_t& gr,
std::enable_if<
std::is_equal<SOME_TRAIT<Graph_t>::type,VertexProp>,T
>::type* = nullptr
)
{
// do something only for graphs having VertexProp
}
I'm ok with type traits in the general case (at least, I think so...), but in this case it's a third party type (boost::adjacency_list
).
And I can't find in the provided traits the typedef giving me that type. I also checked the included code in the manual, but didn't help.
How can I access that type ?
You can get the type via the property_map
trait. In fact the value-type is a trait of that property map :)
So to detect the vertex bundle:
template <typename Graph, typename Bundle = typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
using VBundle = typename boost::property_traits<Bundle>::value_type;
Making that more readable with whitespace:
template <
typename Graph,
typename Bundle =
typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
using VBundle =
typename boost::property_traits<Bundle>::value_type;
You can see that we ask the property_traits
of the vertex_bundle_t
property-map.
To check that it is the expected type:
template <typename Graph>
using HasVertexProp = std::is_same<VertexProp, VBundle<Graph> >;
Now you can use SFINAE. Or, as I'd sugegst for a case like this: tag dispatch;
namespace detail {
template <typename Graph_t>
void foo(const Graph_t& g, std::true_type) {
print_graph(g, std::cout << "Graph with VertexProp bundle: ");
}
template <typename Graph_t>
void foo(const Graph_t& g, std::false_type) {
print_graph(g, std::cout << "Graph with other/missing properties: ");
}
}
template <typename Graph_t>
void foo(const Graph_t& g) {
detail::foo(g, HasVertexProp<Graph_t>{});
}
Let's test it:
int main() {
graph1_t g1(4);
graph2_t g2(4);
foo(g1);
foo(g2);
}
Prints
Graph with VertexProp bundle: 0 <-->
1 <-->
2 <-->
3 <-->
Graph with other/missing properties: 0 <-->
1 <-->
2 <-->
3 <-->