C++ 访问图形束属性类型,以便在SFINAE中使用

C++ 访问图形束属性类型,以便在SFINAE中使用,c++,typetraits,boost-graph,C++,Typetraits,Boost Graph,我有一些代码可以处理不同类型的(boost)图,我想为具有特定bundle属性的图做一些特殊的事情 例如,这: struct VertexProp { // some data }; 我的代码可以使用两种类型的图形: using graph1_t = boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, VertexProp > ; 使用graph

我有一些代码可以处理不同类型的(boost)图,我想为具有特定bundle属性的图做一些特殊的事情

例如,这:

struct VertexProp
{
    // some data
};
我的代码可以使用两种类型的图形:

using graph1_t  = boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    VertexProp
    > ;
使用graph1\u t=boost::邻接列表<
boost::vecS,
boost::vecS,
boost::无向,
垂直旋转
> ;

使用图形2\u t=boost::邻接列表<
boost::vecS,
boost::vecS,
boost::无向
> ;
我的目的是使用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
}
模板
福娃
(
常数图,
std::启用_if<
std::等于T吗
>::type*=nullptr
)
{
//仅对具有VertexProp的图形执行某些操作
}
我对一般情况下的类型特征没有意见(至少我认为是这样),但在这种情况下,它是第三方类型(
boost::adjacence\u list

我在typedef中找不到给我那种类型的。 我也查阅了手册,但没有帮助


如何访问该类型?

您可以使用模板参数来命名某些
图形的嵌套类型,然后确定是否有任何嵌套类型是
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>...>{}>
{} 

您可以通过
属性映射
trait获取类型。事实上,值类型是该属性映射的一个特征:)

因此,要检测顶点束:

template <typename Graph, typename Bundle = typename boost::property_map<Graph, boost::vertex_bundle_t>::type>
    using VBundle = typename boost::property_traits<Bundle>::value_type;
现在你可以使用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>{});
}
印刷品

Graph with VertexProp bundle: 0 <--> 
1 <--> 
2 <--> 
3 <--> 
Graph with other/missing properties: 0 <--> 
1 <--> 
2 <--> 
3 <--> 
带有VertexProp束的图形:0 1. 2. 3. 具有其他/缺少属性的图形:0 1. 2. 3.
谢谢您的回答,我需要一些时间来分析。当然可以。请随意提问。如果另一个模板参数匹配,这也会起作用。最好是通读图书馆的特点。@sehe我不知道你的意思。这会检查模板参数是否匹配。哦,我想我明白了。无论如何,我会留下这个答案,因为它可能对OP有用。谢谢(再次)Sehe,你是我真正的BGL导师!;-)我会仔细检查的。我喜欢标记分派方法。@kebs顺便说一句,我希望混合中有更多的类型,否则您可以简单地
foo(graph1\u t){;foo(图形),:)但是的,这甚至适用于其他模型:啊,是的,当然是重载。事实上,我不能在我的用例中使用重载,因为代码实际上是库的一部分,并且只有在某些特定的“showcase”中我才需要一个bundle属性(并检测它)。但在一般情况下,我需要坚持使用一般的图类型,因此我将坚持使用您描述的方法。好的,刚刚尝试过,非常完美,非常优雅的解决方案!谢谢。同样,在BGL手册中查找信息并不容易。(供参考,此处为:)
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> >;
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 <-->