访问图形包 属性 类型,以便在 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>{});
}

我们来测试一下:

Live On Coliru

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