我有一些代码可以处理不同类型的(增强)图,我想对具有某些特定bundle属性的图做一些特殊的事情。
例如,此:
struct VertexProp
{
// some data
};
我的代码可以使用两种类型的图形:
using graph1_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
VertexProp
> ;
或
using graph2_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS
> ;
我的意图是使用SFINAE启用仅处理此特定情况的功能:
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
}
我一般情况下都可以使用类型特征(至少,我认为是...),但是在这种情况下,它是第三方类型(boost::adjacency_list
)。
而且我在the provided traits中找不到给我该类型的typedef。我也检查了手册中的the included code,但没有帮助。
如何访问该类型?
您可以使用模板模板参数来命名某些Graph_t
的嵌套类型,然后确定是否有任何嵌套类型为VertexProp
,如下所示:
template<template<typename ...> class Graph_t, typename ...Props>
auto foo(Graph_t<Props...>)
-> std::enable_if_t<
std::disjunction<std::is_same<VertexProp, Props>...>{}>
{}
您得到:
foo(graph1_t{}); // ok
foo(graph2_t{}); // error
您可以通过property_map
特性获得类型。实际上,值类型是该属性映射的特征:)
因此要检测顶点束:
template <typename Graph, typename Bundle = typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
using VBundle = typename boost::property_traits<Bundle>::value_type;
要检查它是否为预期的类型:
template <typename Graph>
using HasVertexProp = std::is_same<VertexProp, VBundle<Graph> >;
现在您可以使用SFINAE。或者,像我这样的情况建议:标签分发;
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>{});
}
让我们测试一下:
int main() {
graph1_t g1(4);
graph2_t g2(4);
foo(g1);
foo(g2);
}
打印
Graph with VertexProp bundle: 0 <-->
1 <-->
2 <-->
3 <-->
Graph with other/missing properties: 0 <-->
1 <-->
2 <-->
3 <-->