3

我正在处理一个最初使用 GNAT 3.13a1 编译的遗留 Ada 95 项目(继承自其他公司)。我已将编译器更新到 GNAT 4.7.4,以访问一些我想在进一步开发中使用的 GNAT 库,但我使用的是 -gnat95 标志。

我无法编译特定文件。这有点奇怪,因为它被命名为“Ada.Calendar.GMT”。这是新编译器的一个问题,它抱怨我无法定义一个包,它是 Ada 包树中包的子包。我认为这不是太大的问题,所以我将包的名称更改为“GMT_Library”,导入 Ada.Calendar 以访问它的类型,并更改文件的名称以适应(以防止进一步的编译器警告)。

但是现在编译器抱怨将 Ada.Calendar.Time 转换为 Duration 是无效的。具体来说,我收到以下错误:

180.       D := Duration (Date);
                         |
     >>> illegal operand for numeric conversion

除了更改包的名称和导入 Ada.Calendar 之外,我没有以任何其他方式更改此源文件或相应的规范文件。为什么这是 GNAT 3.13a1 中允许的操作?为什么它不再起作用,有解决办法吗?

编辑:

D 是 Duration,Date 是 Ada.Calendar.Time。

经过进一步调查,最初的开发人员似乎大多复制了此处定义的 Ada.Calendar 的实现。该文件在拆分过程中执行相同的转换。那么为什么标准库可以这样做呢?

4

3 回答 3

3

Ada.Calendar.Time 是私有类型,只有 Ada.Calendar 的私有部分或包体或 Ada.Calendar 的任何子项(在您的情况下为 Ada.Calendar.GMT)才能看到该类型的完整声明,并且类型转换工作需要时间的完整声明(请注意,尽管不需要持续时间的范围来支持时间的完整范围,因此您可能也有一些问题。这高度依赖于实现)。

在 GNAT 中,默认情况下禁止在运行时创建或修改任何包(Ada. 、System.、GNAT.*),但使用 -gnatg 编译将启用此功能。(不建议使用 -gnatg 编译其他包,因为它还会打开一堆警告、样式检查等,您可能不需要/不想要)

于 2014-09-23T06:28:12.887 回答
2

Ada.Calendar可以将 a 转换Ada.Calendar.Date为 a Duration,因为它可以看到私有视图,就像Ada.Calendar.GMT您可以编译它一样。

@egilhh 是正确的,您可以使用它-gnatg来启用它,我不一定反对它(尽管您可能在编译应用程序的某些部分时遇到问题with Ada.Calendar.GMT;)。

作为替代方案,您可以Ada.Unchecked_Conversion在重命名的GMT_Library.

无论您采用哪种方式,请注意Ada.Calendar.TimeGNAT 95 和 GNAT 05 之间的时代变化。在 GNAT 95 中,时代是 Unix 时代 (1970-01-01 00:00:00.00)。最简单的方法可能是使用Ada.Calendar.Time_Of (Year => 1970, ...), 转换为Duration, 作为计算的基础。

于 2014-09-23T08:05:01.783 回答
0

当您想到它时,时间是特定的时刻,而持续时间表示自特定事件以来经过的时间。因此,从一个转换为另一个在语义上没有意义,这就像从公斤转换为米(或对美国人来说是磅转换为英寸)。

现在,GNAT 运行时本身并没有在 Ada 中实现,而是在稍微不同的版本中实现,具有不同的权限和设置(这就是为什么必须使用-gnatg例如编译它的原因)。当然,差异是微妙的。

在与 C 库(没有那么强的类型)交互时,通常情况下我们最终不得不以在 Ada 这样的强类型语言中没有意义的方式转换类型,所以你不应该这样做在您自己的包裹中也是如此。也许使用 anUnchecked_Conversion会起作用,但我真的不推荐它。

试图Ada.Calendar.GMT仅仅根据它的名字来猜测你的包的意图(总是有风险的),在我看来你应该看看 Ada05 的Ada.Calendar.Time_Zones包或者也许Ada.Calendar.Conversions. 从技术上讲,这些不是 Ada95,但我相信它们是兼容的。

于 2014-09-23T08:05:57.710 回答