C++带有继承的对象和基类的variadic函数

发布于 2025-01-27 11:50:41 字数 2953 浏览 2 评论 0原文

我正在编写一个课程来实施和信号槽机制。 该信号可以发出一系列事件,这些事件均来自称为“ base_event”的基本结构。以下是我定义base_event的方式和派生结构的示例:

struct base_event
{
        std::string _id = "base_event";
};

struct select_next_event : public base_event
{
        select_next_event(uint32_t tr_num) : base_event(), _tr_num(tr_num)
        {
                base_event::_id = "select_next_event";
        };

        uint32_t _tr_num;
};

然后,我的发射功能签名是:

template<typename... Args>
void emit(Args... args)
{
   ..... All the logic .....
}

然后,当我想发出事件时,我会写下类似的内容:

slot.emit(select_next_event{3});

到达那里,一切正常。

我的问题是,我想在我的库中添加异步(非阻止)发射功能。为了实现这个目标,我写下了第二个功能(我使用的是C ++ 20,以便我可以完成完美的转发):

void emit_async(Args... args)
{
     auto send_async = std::async(std::launch::async, 
                [this, ... args = std::forward<Args>(args)](){ emit(std::forward<Args>(args)...); });
}

如果写作,就会出现问题:

slot.emit_async(select_next_event{3});

然后,当我在插槽函数中读取事件时, _tr_num的值不会转发(始终等于0),

但是,如果我写的话:

auto send_async = std::async(std::launch::async, 
                [this](){slot.emit(select_next_event{3});});

_tr_num 的值正确地转发到插槽函数。

我看不到我的错误在哪里?

pi -r

[edit]

根据我的要求,对我缺乏清晰度,请找到一个最小的示例,证明了我的问题:

#include <iostream>
#include <utility>
#include <future>
#include <vector>

struct base_event
{
        std::string _id = "base_event";
};

struct select_next_event : public base_event
{
        select_next_event(uint32_t tr_num) : base_event(), _tr_num(tr_num)
        {
                base_event::_id = "select_next_event";
        };

        uint32_t _tr_num;
};

template<typename... Args>
void emit(Args... args)
{
        int i = 0;

        ([&] (auto & arg)
        {
                ++i;
                std::cout << "input " << i << " = " << arg._id.c_str() << " " << arg._tr_num << std::endl;
        } (args), ...);
}


template<typename... Args>
void emit_async(Args... args)
{
     auto send_async = std::async(std::launch::async,
                [... args = std::forward<Args>(args)](){ emit(std::forward<Args>(args)...); });
}

int main()
{
    emit(select_next_event{3});

    //emit_async(select_next_event{3}); // if added, it produces a compilation eror
}

我确实将代码编译为:

g ++ -std = c ++ 20 -O2 -WALL -PESTONTIC -PTHREAD MAIN.CPP&amp;&amp; ./a.out

我认为这个示例提出了我遇到的问题,就像我删除了异步的评论一样,我确实有一个汇编错误:

main.cpp:38:82: error: binding reference of type ‘std::remove_reference<select_next_event>::type&’ {aka ‘select_next_event&’} to ‘const select_next_event’ discards qualifiers

我希望现在我对我的问题有了更明确的解释!如果有任何东西缺少/误导,请告诉我!

I am writing a class to implement and signal-slot mechanism.
The signal can emit a series of events that are all derived from a base struct called "base_event". Below is how I defined the base_event and an example of a derived struct:

struct base_event
{
        std::string _id = "base_event";
};

struct select_next_event : public base_event
{
        select_next_event(uint32_t tr_num) : base_event(), _tr_num(tr_num)
        {
                base_event::_id = "select_next_event";
        };

        uint32_t _tr_num;
};

Then my emit function signature is:

template<typename... Args>
void emit(Args... args)
{
   ..... All the logic .....
}

Then when I want to emit an event, I write something like:

slot.emit(select_next_event{3});

Up to there, everything is working fine.

My issue is that I would like to add an asynchronous (non-blocking) emit function to my library. To that goal, I write a second function (I am using c++20 so I can do perfect forwarding):

void emit_async(Args... args)
{
     auto send_async = std::async(std::launch::async, 
                [this, ... args = std::forward<Args>(args)](){ emit(std::forward<Args>(args)...); });
}

The problem arises if I write:

slot.emit_async(select_next_event{3});

Then when I read the event in my slot function, the value of _tr_num is not forwarded (always equal to 0)

However, if I write :

auto send_async = std::async(std::launch::async, 
                [this](){slot.emit(select_next_event{3});});

Then the value of _tr_num is correctly forwarded to the slot function.

I do not see where is my error?

Pi-r

[EDIT]

As requested, and sorry for my lack of clarity, please find bellow a minimal example that demonstrates my problem:

#include <iostream>
#include <utility>
#include <future>
#include <vector>

struct base_event
{
        std::string _id = "base_event";
};

struct select_next_event : public base_event
{
        select_next_event(uint32_t tr_num) : base_event(), _tr_num(tr_num)
        {
                base_event::_id = "select_next_event";
        };

        uint32_t _tr_num;
};

template<typename... Args>
void emit(Args... args)
{
        int i = 0;

        ([&] (auto & arg)
        {
                ++i;
                std::cout << "input " << i << " = " << arg._id.c_str() << " " << arg._tr_num << std::endl;
        } (args), ...);
}


template<typename... Args>
void emit_async(Args... args)
{
     auto send_async = std::async(std::launch::async,
                [... args = std::forward<Args>(args)](){ emit(std::forward<Args>(args)...); });
}

int main()
{
    emit(select_next_event{3});

    //emit_async(select_next_event{3}); // if added, it produces a compilation eror
}

I do compile the code with:

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

I think this example presents the problem I have as if I remove the comment for the async, I do have a compilation error:

main.cpp:38:82: error: binding reference of type ‘std::remove_reference<select_next_event>::type&’ {aka ‘select_next_event&’} to ‘const select_next_event’ discards qualifiers

I do hope that now I have created a clearer explanation of my issue! If anything is missing/misleading, please let me know!

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

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

发布评论

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

评论(1

策马西风 2025-02-03 11:50:41

这里有两个问题。

首先,emit_async(args ... args)按值传递,因此args ...始终是一个值类型,您需要添加转发参考< /em>对此。

第二和更重要的是,您使用 init-capture [... args = std :: forward&lt; args&gt;(args)构建args] ,但是由于lambda的operator()是隐式const,因此您无法在功能正文中转发args,因为args是另外const - Qualified,而是需要添加Mutable lambda

template<typename... Args>
void emit_async(Args&&... args) {
  auto send_async = std::async(
    std::launch::async,
    [...args = std::forward<Args>(args)] mutable 
      { emit(std::forward<Args>(args)...); });
}

演示

There are two problems here.

First, emit_async(Args... args) is pass by value, so Args... is always a value type, you need to add forwarding reference to it.

Second and more important, you construct args with init-capture [... args = std::forward<Args>(args)], but since lambda's operator() is implicitly const, you cannot forward args in the function body since args are also const-qualified, instead you need to add mutable keyword for lambda

template<typename... Args>
void emit_async(Args&&... args) {
  auto send_async = std::async(
    std::launch::async,
    [...args = std::forward<Args>(args)] mutable 
      { emit(std::forward<Args>(args)...); });
}

Demo

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