2

我目前正在为需要预编译二进制/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;
4

2 回答 2

2

如果确切的位范围或位数很重要,大多数系统都会提供带有类型定义的<types.h>或标头。<inttypes.h>我认为没有充分的理由在这个问题上抛出继承。如果指定的类型或模板类型不符合要求,您还可以std::numeric_limits与 Boost 的宏一起使用来生成有意义的编译时断言。BOOST_STATIC_ASSERT()要求可以是整数与浮点数、范围、最小可表示值、精度等。例如:

#include <limits>
#include <inttypes.h>
#include <boost/static_assert.hpp>

template<class T, int bits> T Add(const T& a, const T& b)
{
    BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer     );
    BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_signed      );
    BOOST_STATIC_ASSERT( std::numeric_limits<T>::digits == bits );

    return a + b;
}

如果 std::numeric_limits 没有您的所有类型,请使用模板特化来扩展和实现它们。

于 2009-10-14T00:23:21.963 回答
0

是的,我想我已经得到了我需要的东西,至少现在是这样。

以上提及的

class ConstraintExpressionArgument : public Expression;
template<typename ValueType>
class Constraint : public ConstraintExpressionArgument;

让我走上了将类型与约束分开的正确轨道。

于 2009-10-16T15:42:27.250 回答