我有一个Ada任务,Do_Something
,需要"调用"本身。我认为它来自C ++的方式,我有一个运行void Do_Something()
的线程,有时候void Do_Something()
需要生成更多运行void Do_Something()
的线程。
task body A_Task is
new_task: access A_Task;
my_level: Natural;
begin
accept Do_Something(level: in Natural) do
my_level := level + 1;
end Do_Something;
if my_level < 4 then
new_task := new A_Task;
new_task.Do_Something(my_level);
end if;
end A_Task;
GNAT至少不会这样,在new_task.Do_Something(my_level);
报告错误,因为
task type cannot be used as type mark within its own spec or body
然而,在任务之外添加这样的程序很容易避免这种情况:
procedure Circumvent(level: Natural) is
new_task: access A_Task;
begin
new_task := new A_Task;
new_task.Do_Something(level + 1);
end Circumvent;
然后将if
正文中的A_Task
声明修改为:
if my_level < 4 then
Circumvent(my_level);
end if;
后一个版本通过GNAT(现在我们有一个M *** W *** E)并且该程序运行得很好,即使是在我昨晚玩的非常重要的例子中。
这种解决方法看起来非常简单,我不明白为什么编译器应该首先引发第一个错误!我想我必须以完全错误的方式攻击这个问题。这被认为是很好的Ada技术,如果没有,那么做Ada的方式会是什么样的呢?
答案 0 :(得分:4)
此行为在RM 8.6(17/3)中指定: &#34;如果一个用法名出现在type_declaration的声明性区域中并且表示相同的type_declaration,那么它表示该类型的当前实例(而不是类型本身);&#34;
这意味着该类型的实际名称不能用于实例化不同的对象。
然后,包装器(就像你的包装器)就是这样做的一种方式。
子类型也应该有效subtype Foo is A_Task;
请注意,C ++的思考/做事方式很少是Ada的做事方式