【问题标题】:How to build up a directed graph at compile time?如何在编译时构建有向图?
【发布时间】:2014-05-28 08:15:30
【问题描述】:

我想在编译时用 C++11 构建一个有向图。

示例:我有一些线程和队列并且想要建立:

+-------+            +---------+            +-------+
| f_gen | -> QGen -> | f_check | -> QOut -> | f_out |
+-------+            +---------+    ^       +-------+
                          |         |
                         \|/        |
                          |         |
                        QProc       |
                          |         |
                         \|/        |
                          |         |
                     +-----------+  |
                     | f_process | /
                     +-----------+

请注意,这只是一个示例:解决方案应处理 每个节点/边类型的有向图。

我想这样写:

make_directed_graph<Queue, Thread>(
// Queues
{
   // ID, Type of Queue, queue size
   { 0, std::string, 100 }, // QGen
   { 1, int, 250 },         // QProc
   { 2, std::string, 500 }  // QOut
},
// Threads
{ 
   // Fn, thread cnt, in queues, out queues
   { f_gen, 5, {}, { qref(0) } }, // ID 1: QGen 
   { f_check, 30, { qref(0) }, { qref(1), qref(2) }}, // IDs of queues
   { f_process, 75, { qref(1) }, { qref(2) }},
   { f_out, 12, { qref(2) }, {} }
});

请注意,这只是一个想法 - 任何其他可能性 写下来对我来说很好。

我设法实现了make_tree 函数。 它可以像

一样使用
make_tree< arexp, int >(
     { '+', { 1, 2, { '*', { 3, 4, 5 } } } } )

这里有一个很大的区别:节点和边可以创建 苍蝇' - 无需引用任何现有的。

有向图最大的问题是如何引用一个对象 / 之前定义的结构/部分。比如:如何引用一个 定义线程时排队(反之亦然)。

我的问题:

  1. 是否可以在编译时定义有向图?
  2. 如果是这样,您能否给我一个提示如何实现它?

【问题讨论】:

  • 不知怎的让我想起了stackoverflow.com/a/2024573/396583 :)
  • 你真的想要二合字母和三合字母吗?请注意它们是 C 和 C++ 的实际特性
  • 嗯:看起来“有向图”这个词有不止一种用法:使用“有向图”重新表述。
  • “拥有”任意图形表示与能够将其用于某事不同。对于元处理,我通常建议从函数重载集而不是指针来形成结构。但我们确实需要知道手头的问题。
  • 为什么不只是一个队列列表,然后创建多个使用这些队列的线程?为什么要额外努力将其建模为编译时有向图?

标签: c++ c++11 compile-time


【解决方案1】:

这通常是可能的,因为您使用指针标识对象,而这些指针是有效的非类型模板参数。

Queue<std::string> QGen(100); // No need for an ID, we have &QGen.
// We  *do* need to pass the Queue type to figure out the type of &QGen.
Thread<void, nullptr, std::string, &QGen> f_gen(5);

当然,您不能以这种方式定义循环图。

【讨论】:

  • 使用 extern 前向声明循环图。
  • @brianbeuning:行不通。即使使用extern,您也需要指定类型。在这种情况下,类型本身将具有循环依赖关系。
  • 这不能回答问题:我需要一个有向图(对象)(由“make_directed_graph”返回),而不是一系列队列和线程。然而,答案解决了类型处理/规范的问题。
【解决方案2】:

我认为我离解决方案更进了一步(但尚未完成):

我的错误是不需要直接写下图形本身,而是某种表示形式。以下源代码至少可以编译:

directed_graph const dg(
  make_directed_graph<Node, Edge>(
     {
        { 1, "qgen" },
        { 2, "qproc" },
        { 3, "qout" },
        { "fgen", {}, { 1 } },
        { "fcheck", { 1 }, { 2, 3 } },
        { "fproc", { 2 }, { 3 } },
        { "fout", { 3 }, {} }
     }));

鉴于 make_directed_graph 和适当的 initializer_list 的以下定义:

class NodeRef {
public:
   NodeRef(int nid);
};

class digraph_initializer {
public:
   digraph_initializer(int id, std::string const & s);
   digraph_initializer(
      std::string const & s,
      std::initializer_list< NodeRef > const nr_in,
      std::initializer_list< NodeRef > const nr_out);
};

class directed_graph {
};

template< typename TNode, typename TEdge >
directed_graph make_directed_graph(
   std::initializer_list<digraph_initializer> const & dgi);

还有一些开放点:

  1. 如何确保边定义时才能被引用?
  2. 在编译时从 initializer_list 构建“真实”图。
  3. 添加模板(参数)以处理/初始化任意节点/边。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    相关资源
    最近更新 更多