我目前正在为需要预编译二进制/DLL(它将是跨平台的)的产品设计面向公众的 C++ API。我希望 API 允许用户使用我们支持的任何 POD(如果适用),但基本要求是最大的灵活性和二进制兼容性。我正在做一些类似于 CPLEX 的 API 的事情(这是几个灵感之一),但我认为指定类型信息的方式可能比他们所做的更好(关于 IloInt、IloNum、IloAny、Ilo* var等,见链接(希望)用于 IloExtractable 分支)而不会弄乱二进制兼容性。我错了吗?我有一些想法,但我不记得它是什么,或者它是否会起作用,我相信它类似于访问者或装饰者模式,但对于类型,有人可以在这个问题上启发我吗?我面前有一本由 GoF 编写的设计模式书。
注意:这里可能出现的任何语法错误都不是当前问题的一部分。
我认为我不能使用的示例以及原因:
可能......但这可能会使表达式树变得复杂。
template<typename ValueType>
Constraint : public Expression;
可能会影响未来的扩张。
IntConstraint : public Expression;
LongConstraint : public Expression;
DoubleConstraint : public Expression;
丑陋如罪,可能会引起很多微妙的问题。
union Value
{
int AsInt,
float AsFloat
};
class Constraint : public Expression
{
public:
Value GetValue(Edge);
void SetValue(Value, Edge);
void SetUpper(Value, Vertex);
void SetLower(Value, Vertex);
...
};
编辑:作为对 Mads Elvheim 的回应(在找到此链接后),我现在意识到我不需要从我的可能性中排除模板,这很好,但我仍然不确定这是最好的主意 - 至少对于 Constraints 类(即使它在概念上是合理的),请原谅我没有我想的那么清楚。
为了使我的 API 易于使用,我使用 bnf 定义了语法(这对我来说相当新)。这导致了表达式、约束和其他将与约束交互的类的抽象语法树。因为其他类将与约束交互,所以我宁愿避免在“最后一分钟”之前尽可能多地传递类型信息。可以这么说。我觉得我可能错过了一个抽象层次。
学习 CPLEX 给我的印象是,他们通过遵循数字域(整数和实数)、线性方程表达式(当然)以及相应的可能性来建模他们的类型,这绝对是有道理的,嗯……
(显然我不能发布多个链接,因为我是新用户。)
编辑 2:作为第一步,我决定ConstraintExpressionArgument
在 Constraint 和 Expression 类之间添加一个,这样我仍然可以在我的表达式树中识别一个约束,而无需知道它所操纵的类型是好的。
我可能忽略提及的另一个细节是,与在 CPLEX 中 Constraint 类本身不可用的情况不同,我的 Constraint 类目前是一个可用的用户类,但就像在 CPLEX 中一样,我也想留出扩展空间(因此是打字问题)。 ..
无论如何,目前我有相当于
class ConstraintExpressionArgument : public Expression;
template<typename ValueType>
class Constraint : public ConstraintExpressionArgument;