【问题标题】:Member template function definition and incomplete types成员模板函数定义和不完整类型
【发布时间】:2021-07-25 18:22:58
【问题描述】:

我正在尝试实现以下目标,但我不确定这是否可行,如果可以,如何实现:我有一个头文件,我在其中声明了一个具有模板成员函数的类,该函数返回对不完整类型的引用.为了让它更具体一点,假设它处理事件,它是这样声明的:

struct EventConnection;

class EventHandler {
public:
    template<typename Func>
    const EventConnection& connectToEvent(EventType t, Func f);

    void disconnect(const EventConnection& connection);
};

在这种情况下,EventConnection 只是我希望客户端代码稍后提供给disconnect 的一些内部结构,我想在此处将其保留为不完整的类型。

我知道,从理论上讲,模板的定义应该放在标题中,或者可以在 .cpp 文件中提供,只要使用将使用的类型显式实例化模板即可。但是在这种情况下,我不能列出这些,因为它非常随意,因此我认为我被卡住了,因为如果我真的希望 EventConnection 只在标题中声明,那么我不能提供模板定义在标题中,但由于我无法在 .cpp 文件中列出模板实例化,因此我无法在同一个文件中提供模板定义(我可以在其中包含/定义我的不完整类型并在模板)。

我是否正确评估了这一点并且应该重新考虑这一点?或者有没有办法在标头中转发声明一个类型,并以某种方式在源文件的模板主体中使用完整的类型?

【问题讨论】:

  • 曾几何时引入了export关键字,但正如cppreference所说export的实现很少见,并且在细节上存在分歧
  • 类型擦除通常用于实现这一点:您定义一个接口,并在标题中定义的函数模板中专门为Func类型实现它。然后,将该接口传递给处理EventConnection 内部的不透明函数。这或多或少是std::function 的实现方式,这可能会直接解决您的问题:)
  • @dyp 谢谢,我会调查的!

标签: c++ templates incomplete-type


【解决方案1】:

模板定义确实必须在实例化时可见。

显式实例化可以避免隐式实例化。

由于您不能使用显式实例化,并且不想向用户提供定义,您可以使用类型擦除类型而不是模板。

从名字上看,std::function 似乎是个不错的候选人:

const EventConnection& connectToEvent(EventType, std::function<void (EventType/*, ...*/)>);

或接口:

const EventConnection& connectToEvent(EventType, IEventVisitor&);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    相关资源
    最近更新 更多