【问题标题】:Using containers with typed actors give "incomplete type" errors使用带有类型化actor的容器会产生“不完整类型”错误
【发布时间】:2022-01-26 15:37:34
【问题描述】:

当我将容器添加到键入的消息时,我收到“不完整类型”错误消息。这是一个简单的例子。注意 \"display_behavior\" 消息中的最后一个参数是一个字符串吗?这个演员编译并运行得很好。

using DisplayActor = caf::typed_actor<
    caf::result<void>(display_behavior, time_point<system_clock>, string)>;

class DisplayState {
private:
    shared_ptr<Displayable> displayable_;

public:
    explicit DisplayState(std::shared_ptr<Displayable> displayable) :
        displayable_(displayable) {}

    DisplayActor::behavior_type make_behavior() {
        return {
            [this](display_behavior, time_point<system_clock> quackTime, string behavior) {
                displayable_->displayBehavior(quackTime, behavior);
            }
        };
    }
};

using DisplayImpl = DisplayActor::stateful_impl<DisplayState>;

现在我用一个向量替换字符串参数:

using DisplayActor = caf::typed_actor<
    caf::result<void>(display_behavior, time_point<system_clock>, vector<string>)>;

class DisplayState {
private:
    shared_ptr<Displayable> displayable_;

public:
    explicit DisplayState(std::shared_ptr<Displayable> displayable) :
        displayable_(displayable) {}

    DisplayActor::behavior_type make_behavior() {
        return {
            [this](display_behavior, time_point<system_clock> quackTime, vector<string> behavior) {
                //displayable_->displayBehavior(quackTime, behavior);
            }
        };
    }
};

using DisplayImpl = DisplayActor::stateful_impl<DisplayState>;

我收到以下错误:

难道我做错了什么?

  • 嗯,我遇到了序列化问题吗?如果我将 vector<string> 包装在一个类中,然后将该类声明为 unsafe message,那么程序将编译并通过我的测试。我仍然有点困惑,因为this page 显示了如何编写检查重载,而point_3d 字段有一个向量成员变量。

标签: c++-actor-framework


【解决方案1】:

如果您看到这种错误,通常意味着您使用的类型没有分配给它的类型 ID。

CAF 使用类型 ID 为消息生成元数据。基于此元数据,CAF 可以实现“类型切换”以根据签名自动调度消息处理程序。从 0.18.5 开始,CAF 将类型 ID 分配给标准库的某些类型,例如 std::string(请参阅 https://github.com/actor-framework/actor-framework/blob/0.18.5/libcaf_core/caf/type_id.hpp#L375)。

但是,std::vector&lt;std::string&gt; 默认没有类型 ID。这意味着您的应用程序需要分配一个。样板代码看起来有点像这样:

CAF_BEGIN_TYPE_ID_BLOCK(my_types, first_custom_type_id)

  CAF_ADD_TYPE_ID(my_types, (std::vector<std::string>))

CAF_END_TYPE_ID_BLOCK(my_types)

稍后您还需要确保初始化运行时类型信息。如果您使用的是CAF_MAIN,那么它只是:

CAF_MAIN(caf::id_block::my_types)

如果您不使用宏,则需要添加这些行开始actor_system(最好是main):

caf::init_global_meta_objects<caf::id_block::my_types>(); // custom types
// ... module types, e.g., caf::io::::init_global_meta_objects() ...
caf::core::init_global_meta_objects(); // default types

当前(0.18.5),该手册讨论了Configuring Actor Applications 下的类型ID。在本节中主要是出于历史原因,因为添加了用于通过 actor-system 配置的运行时类型信息。也许类型 ID 应该有自己的部分,或者至少移到手册的“类型检查”部分。

我仍然有点困惑,因为这个页面显示了如何编写检查重载,并且 point_3d 字段有一个向量成员变量。

如果您希望在消息中单独发送此类型,则需要该类型的类型 ID。这是模式匹配/类型切换所必需的。序列化程序可以处理 std::vector 并且不需要类型 ID。它们在inspect API 上运行。美好的一天,C++ 希望带有(静态)类型反射,并且大多数 inspect 重载可以由 CAF 自动生成。

【讨论】:

  • neverlord 再次提供了一个彻底而有帮助的答案。我不知道你在 caf 项目中的角色,但我希望你很高兴听到我的团队对其能力印象深刻。在运行时启动actors的能力使我们能够满足一些具有挑战性的并发要求。
  • 我很高兴 CAF 很适合你!我是创建者/维护者,所以我总是很高兴看到更多用户使用该框架。 :)
  • 如果您有兴趣,我很乐意在某个时候带您参观我们的建筑。我们结合了您文章中的不同示例,构建了一个强类型、有监督的 N:1 生产者-消费者架构。最酷的部分是每个参与者只依赖于一个接口。这允许我们在不调用任何参与者的情况下对大部分代码库进行单元测试。此外,通过这种方法,我们可以隔离 N:1 演员系统并使用 GoogleMock 对其进行练习。就像我说的那样,我很乐意在某个时候带您参观并听取反馈。我们甚至可以围绕它生成好的内容。
  • 听起来真棒!请随时通过 PM、电子邮件或此联系表格与我们联系:cafcademy.com/contact-us。 :)
猜你喜欢
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
相关资源
最近更新 更多