我对C ++还是很陌生,但是在锁定期间,我一直在尝试使自己的技能更加多样化。 我正在尝试使用SFML编写基于节点的声音处理工具。我想要一个包含所有节点输入和输出的结构。但是,我显然无法将任何类型连接在一起。我正在寻找与Blender对其节点类型进行相似的操作。 以下屏幕录像显示了我的意思:绿色输出类型与其他输入类型不兼容。
我认为struct NodeInOut
可能是解决此问题的有用方法:每次创建新Node时,我都会分配一个类型,在将Node连接在一起的逻辑中,请确保不兼容类型不可连接。但是,每当我创建一个新的Node定义时,我都需要传递一个类型。
我对Node类的想法是,它的结构应类似于此草草制作的图表。
有人对如何执行此操作有任何想法,或者如何以不同的方式构造它,以至于这不是问题吗?
除了SFML样板之外,我还没有编写任何代码。
答案 0 :(得分:2)
是的,您可以拥有一个“类型类型”。
但是,请注意,用户在运行时连接节点。因此,这是一个运行时问题,不是您可以在编译时解决的问题。
换句话说,只需使用包含您的节点接受/发送的任何类型的运行时值,并根据需要比较它们。
答案 1 :(得分:1)
如果我正确理解了这个问题,则应该可以执行以下操作:
特定节点从抽象class Node
继承。
class Node
包含用于列出输入/输出点的纯虚函数:
virtual std::size_t InputCount() const = 0;
virtual const Input &GetInput(std::size_t i) const = 0;
Input &GetInput(std::size_t i) {return const_cast<Input &>(std::as_const(*this).GetInput(i));}
virtual std::size_t OutputCount() const = 0;
virtual const Output &GetOutput(std::size_t i) const = 0;
Output &GetOutput(std::size_t i) {return const_cast<Output &>(std::as_const(*this).GetOutput(i));}
可能还有诸如virtual void Update() = 0;
,DrawGui
之类的东西。
从Node
派生的类具有Input
和Output
对象作为成员,并覆盖GetInput
和GetOutput
以返回这些成员。
(奖金:您也许可以使用magic_get
之类的反射库来自动生成函数。)
class Input
必须以某种方式指向其连接的Output
,方法可能是存储指向拥有连接{的std::weak_ptr
的指针(Node
?) {1}}以及该Output
在节点中的索引。
Output
至少应包含class Output
(或其他内容,具体取决于要支持的值)。也许您会想要在其中存储连接的float value;
的列表(每个元素都是指向Input
的指针以及其中的Node
的索引)。
答案 2 :(得分:1)
如HolyBlackCat's answer下面的评论中所述,这是我的选择:
每个节点都是{final(非虚拟)/----------------------\
|This is a really long |
|string that needs to b|
|reak after it reaches |
|a certain limit. This |
|is a really long strin|
|g that needs to break |
|after it reaches a cer|
|tain limit.This is a r|
|eally long string that|
| needs to break after |
|it reaches a certain l|
|imit. |
\----------------------/
类的成员
这个Node
类有一个Node
和一个std::vector<Input>
,它们代表节点的每个输入和输出(如果您努力尝试,它们可能会变成const)。
您添加了一个名为std::vector<Output>
的私有变量,该私有变量的类型为update
(例如,可以有lambda),这是一种用户定义的更新方法,用于设置输出取决于输入,还有一个称为std::function<void(Node &)>
的公共函数,该函数调用此节点的Update
和后续节点的update
(因为它们也需要更新)
然后对于Update
,您需要一个函数来设置值(可能是模板函数?然后检查类型是否正确并获得兼容的类型,也许使用{{1 }}来存储值),以及与其连接的所有Output
的列表(也许是std::variant
?或者您也可以用{{1}替换Input
})
对于输入,您需要能够将它们连接到一个std::vector<Node*, unsigned>
,因此Node*
或std::weak_ptr<Node>
应该都可以工作,但是由于您需要能够拥有常量,您可以:
Output
来存储默认值,或者Output*
,而无需输入,并且每个悬空的输入都有一个输出,或者std::weak_ptr<Output>
,该对象没有输入,并且输出与目标节点的输入一样多(并一对一连接)。这可能(不是)最好的解决方案,但至少应该可以。