访问图形包 属性 类型,以便在 SFINAE 中使用它
Accessing graph bundle property type, to use it in SFINAE
我有一些代码可以处理不同类型的 (boost) 图,我想为具有特定包的图做一些特别的事情 属性。
例如,这个:
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,
typename Bundle =
typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
using VBundle =
typename boost::property_traits<Bundle>::value_type;
你可以看到我们问vertex_bundle_t
属性-map的property_traits
。
检查它是否是预期的类型:
template <typename Graph>
using HasVertexProp = std::is_same<VertexProp, VBundle<Graph> >;
现在你可以使用SFINAE了。或者,正如我对这样的案例所建议的那样: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>{});
}
我们来测试一下:
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 <-->
我有一些代码可以处理不同类型的 (boost) 图,我想为具有特定包的图做一些特别的事情 属性。
例如,这个:
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,
typename Bundle =
typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
using VBundle =
typename boost::property_traits<Bundle>::value_type;
你可以看到我们问vertex_bundle_t
属性-map的property_traits
。
检查它是否是预期的类型:
template <typename Graph>
using HasVertexProp = std::is_same<VertexProp, VBundle<Graph> >;
现在你可以使用SFINAE了。或者,正如我对这样的案例所建议的那样: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>{});
}
我们来测试一下:
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 <-->