C ++模板-可变参数模板&通过const引用传递 [英] C++ template - variadic templates & pass by const reference

查看:89
本文介绍了C ++模板-可变参数模板&通过const引用传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ThreadPool 类,具有一个入队函数:

I have a ThreadPool class with an enqueue function:

class ThreadPool
{
public:
    //(Code removed here)

    template <typename ... Args, typename Fun>
    JobId enqueue(Fun func, Args ... args);

    //(Code removed here)
}

我在类 Object 上的这些非静态成员函数 loadStuff 上使用它:

And I use it on these non static member function loadStuff on class Object:

class Object
{
    //(Code removed here)
    void init(const PrepareData & prepareData);
    virtual bool loadStuff(const PrepareData & prepareData);
    //(Code removed here)
}

通过调用QObject: :init:

by calling in QObject::init :

void QObject::init(const PrepareData &prepareData)
{
    threadPool->enqueue(&loadStuff, this, prepareData);
}

但是我注意到prepareData是通过副本传递的,它占用了大量内存并减慢了速度

But I noticed that prepareData was passed by copy, which eats significant memory and slows down significantly the program (and is useless).

因此我删除了PrepareData中的复制ctor和赋值运算符。该程序不再编译,因为可变参数模板通过值而不是引用来获取其参数。

So I deleted the copy ctor and assignment operator in PrepareData. The program does not compile anymore, as the variadic template takes its parameters by value and not by reference.

因此,我宣布入队通过引用传递可变参数模板参数: / p>

So I declared enqueue to pass the variadic template arguments by reference:

template <typename ... Args, typename Fun>
JobId enqueue(Fun func, Args&... args);

现在不再调用复制构造函数,但是出现以下错误:

Now the copy constructor is not called anymore, but I get the following error:


object.cpp:21:错误:没有匹配的调用函数

object.cpp:21: error: no matching function for call to

'ThreadPool :: enqueue(bool(Object :: *)(const PrepareData&),Object *,
const PrepareData&)'
threadPool-> enqueue(& prepareType,this,loadStuff);

'ThreadPool::enqueue(bool (Object::*)(const PrepareData&), Object *, const PrepareData&)' threadPool->enqueue(&prepareType, this, loadStuff);

所以我对如何执行此操作非常迷惑。我可以通过传递 const PrepareData& ,而不是传递 const PrepareData * ,但是我想理解为什么它不能与const引用一起使用。

So I'm quite lost on how to do this. I could, instead of passing a const PrepareData &, pass a const PrepareData * by copy, but I would like to understand why it does not work with a const reference.

推荐答案

此:

template <typename ... Args, typename Fun>
JobId enqueue(Fun func, Args ... args);

复制所有 args ,因为它们是所有通过价值传递。参数传递的工作方式似乎有些混乱-调用const引用 enqueue 无关紧要,入队按值接受参数。 init()是通过引用传递的,但 enqueue()不是。

copies all the args because they're all passed by value. There seems to be some confusion with how argument passing works - it doesn't matter that you're calling enqueue with a reference to const, it matters that enqueue takes its argument by value. init() is pass by reference, but enqueue() is not.

您可能想要的是将引用包装传递给数据(按值):

What you probably want instead is to pass a reference wrapper to your data (by value):

threadPool->enqueue(&loadStuff, this, std::ref(prepareData));

这将避免复制 prepareData 并调用 loadStuff()正确。这也使 enqueue()的调用者有责任知道应该复制哪些内容,以及应该引用哪些内容。

This will avoid copying prepareData and call loadStuff() correctly. This also puts the onus on the caller of enqueue() to know which things should be copied and which should be referred to.

尽管, QObject 需要确保 prepareData 的持续时间足够长。我们通过引用 const 来理解它,因此似乎没有任何办法。因此,也许另一种方法是让 init()按值获取其数据:

Although, QObject needs to ensure that prepareData lasts long enough. We take it by reference to const, so it doesn't seem like it has any way of doing that. So perhaps an alternative approach would be have init() take its data by value:

void QObject::init(PrepareData prepareData)
{
    threadPool->enqueue(&loadStuff, this, std::move(prepareData));
}

这篇关于C ++模板-可变参数模板&amp;通过const引用传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆