C ++模板 - 可变参数模板&传递const引用

时间:2016-06-09 16:00:27

标签: c++ c++11 pass-by-reference variadic-templates

我有一个ThreadPool类,其中包含enqueue函数:

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

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

    //(Code removed here)
}

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

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

通过调用QObject :: init:

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

但我注意到prepareData是通过副本传递的,这会占用大量内存并显着减慢程序(并且没用)。

所以我删除了PrepareData中的copy ctor和assignment操作符。该程序不再编译,因为可变参数模板按值而不是通过引用获取其参数。

所以我声明enqueue通过引用传递可变参数模板参数:

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

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

  

object.cpp:21:错误:没有用于调用

的匹配函数      

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

所以我很失落如何做到这一点。我可以,而不是通过const PrepareData &传递const PrepareData *副本,但我想理解为什么它不能用const引用。

1 个答案:

答案 0 :(得分:1)

此:

var brandClass

// Iterate though split classes
jQuery.each( classList, function(i) {
 if ( classList[i].includes('product-wildridge') ) {
 brandClass = classList[i];
}
});

// check specific class for certin keywords
var customTab = function(brandClass) {
 if (brandClass.includes('wildridge') && brandClass.includes('deep') ) {
 return true;
} else {
jQuery('#tab-fabric').css('display', 'none');
 }
}

customTab(brandClass);

复制所有template <typename ... Args, typename Fun> JobId enqueue(Fun func, Args ... args); ,因为它们全部按值传递。对于参数传递的工作原理似乎有些混淆 - 你通过引用const来调用args并不重要,重要的是enqueue通过值来获取它的参数。 enqueue以引用方式传递,但init()不是。

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

enqueue()

这样可以避免复制threadPool->enqueue(&loadStuff, this, std::ref(prepareData)); 并正确调用prepareData。这也使loadStuff()的调用者有责任知道应该复制哪些内容以及应该引用哪些内容。

虽然enqueue()需要确保QObject持续足够长的时间。我们参考prepareData来看待它,所以它似乎没有办法做到这一点。因此,或许另一种方法是const按值获取数据:

init()