如何使用 boost 中的模板相关信号成员来实现模板类?

发布于 2024-09-18 02:04:07 字数 1370 浏览 6 评论 0原文

我尝试实现一个模板类,它需要有一个依赖于模板参数的信号成员。我的第一个想法是像下面这样实现它:

template<class T>
class SignalClass 
{
    typedef boost::signals2::signal<void (T &)> OnReceive;

public:
    SignalClass(const OnReceive::slot_type &_slot)
    {
       m_onReceive.cnnect(_slot);
    }
    virtual SignalClass(){};

    void Send(T &_val)
    {
       m_onReceive(_val);
    }
private:
    OnReceive m_onReceive;
};

该类应该像这样使用:(

class SignaledClass
{
public:
    SignaledClass(void)
    {   
       SignalClass<int>    var1(boost::bind(&SignaledClass::ReceiveINT, this));
       SignalClass<double> var2(boost::bind(&SignaledClass::ReceiveDOUBLE, this));
    }

   void ReceiveINT(int &_val)
   {
      ...
   }

   void ReceiveDOUBLE(double &_val)
   {
      ...
   }
}

顺便说一句:我知道,在构造函数内部创建 SignalClass 对象是没有意义的。这只是为了理解我的问题。

)对我来说,以模板作为信号参数来实现类似委托的概念很重要。

问题是构造函数代码不起作用。

但我找到了一个解决方案。

如果我另外指定一个额外的 typedef

typedef typename OnReceive::slot_type slot_type;

并将其用作构造函数的参数,就像

PushInputSlot(const slot_type& _slot);

它一样有效。 但我不知道为什么。

我希望有人能帮助我。

谢谢, Frank

P.S.:我是 stackoverflow 的新手,这就是为什么我不熟悉这里的规则。希望我以正确的方式完成了一切......;-)......

I try to implement a template class which requires to have a signal member that depends on the template argument. My first idea was to realize it like the following:

template<class T>
class SignalClass 
{
    typedef boost::signals2::signal<void (T &)> OnReceive;

public:
    SignalClass(const OnReceive::slot_type &_slot)
    {
       m_onReceive.cnnect(_slot);
    }
    virtual SignalClass(){};

    void Send(T &_val)
    {
       m_onReceive(_val);
    }
private:
    OnReceive m_onReceive;
};

An that class should be used like:

class SignaledClass
{
public:
    SignaledClass(void)
    {   
       SignalClass<int>    var1(boost::bind(&SignaledClass::ReceiveINT, this));
       SignalClass<double> var2(boost::bind(&SignaledClass::ReceiveDOUBLE, this));
    }

   void ReceiveINT(int &_val)
   {
      ...
   }

   void ReceiveDOUBLE(double &_val)
   {
      ...
   }
}

(BTW: I know, that it makes no sense to create the SignalClass object just inside the constructor. It's just to understand my problem.)

It is important for me to realize a delegate-like concept with a template as signal parameter.

The problem is that the constructor code doesn't work.

But I found a solution.

If I additionally specify an additional typedef like

typedef typename OnReceive::slot_type slot_type;

and use that a parameter for the constructor, like

PushInputSlot(const slot_type& _slot);

the it works.
But I have no real clue why.

I hope that somebody can help me.

Thanx,
Frank

P.S.: I'm new on stackoverflow thats why I'm not familiar with the rules here. Hope I've done everything in the right way... ;-)....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一花一树开 2024-09-25 02:04:07

以下是添加 typename(直接在构造函数参数中或在附加 typedef 中)起作用的原因:

首先,类型 OnReceive 是所谓的“依赖类型” ,因为它取决于模板参数的类型。

然后,模板在编译器中分两个阶段进行处理:第一阶段是编译器遇到模板的源文本时,第二阶段是模板实际实例化时。
在处理的第一阶段,编译器将(应该)尝试尽可能验证模板定义是否正确,但是当涉及依赖类型时,它会遇到问题。由于依赖类型依赖于模板参数,因此编译器不知道实际类型会是什么样子。
特别是,当使用 :: 运算符访问成员时,编译器需要一些帮助来确定该成员是引用成员类型(typedef 或嵌套类)还是非类型成员(变量、枚举等)。如果您知道它应该引用类型,则可以通过在(完整)类型名称之前添加 typename 来解决此问题。
编译器可能遇到问题的另一个地方是区分小于比较中涉及的成员模板和非模板成员。通过在成员模板名称之前(紧接在运算符之后)添加关键字 template 可以解决此问题。

Here is the reason why adding typename (either directly in the constructor argument or in an additional typedef) works:

First, the type OnReceive is a so-called "dependent type", because it depend on the type of the template parameter.

Then, templates are processed in two stages in the compiler: The first stage is when the compiler encounters the source text for the template and the second stage is when the template is actually instantiated.
During the first stage of processing, the compiler will (should) try to validate as far as possible that the template definition is correct, but it runs into a problem when it comes to dependent types. Because a dependent type depends on the template parameters, the compiler does not know what the actual type will look like.
In particular, when accessing a member with the :: operator, the compiler needs some help deciding if the member is expected to refer to a member-type (typedef or nested class) or a non-type member (a variable, enum, etc.). This can be resolved by adding typename before the (full) type-name if you know that it should refer to a type.
The other place where the compiler might have a problem is differentiating between a member-template and a non-template member involved in a less-than comparison. This is resolved by adding the keyword template before the name of the member-template (immediately after the operator).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文