【问题标题】:Template function will not compile when called as a thread模板函数在作为线程调用时不会编译
【发布时间】:2016-02-14 14:45:57
【问题描述】:

我有一个与模板函数和线程有关的问题:

template <class TYPE_size>
void Threader(TYPE_size counter)
{
    counter++;
}
int main()
{
    unsigned int counter = 100;
    thread one(Threader,counter);
    one.join();    
    cout << counter;
}

这不会编译;我明白了:

错误:没有匹配的调用函数 âstd::thread::thread(, 无符号 int&)✘

如果我删除它编译的模板,并且如果我将函数调用更改为标准函数调用而不是线程(仍在使用模板),它就会编译。

有人知道这是为什么吗?

我使用的是 Centos5 64 位。

 error: no matching function for call to âstd::thread::thread(<unresolved overloaded function type>, unsigned int&)â
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.0/../../../../include/c++/4.4.0/thread:124: note: candidates are: std::thread::thread(std::thread&&)
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.0/../../../../include/c++/4.4.0/thread:122: note:                 std::thread::thread(const std::thread&)
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.0/../../../../include/c++/4.4.0/thread:121: note:                 std::thread::thread()

【问题讨论】:

  • 我不记得参数,类型等,但可能是thread one(Threader&lt;counter&gt;,counter)
  • 根据错误,没有期望函数的线程构造函数。默认、复制、移动就可以了。

标签: c++ multithreading templates c++11


【解决方案1】:

没有名为 Threader 的函数。当您编写Threader&lt;int&gt; 或其他内容时,编译器会创建一个函数。如果你然后写Threader&lt;float&gt;,那么编译器会创建一个新函数。您可以提供一个默认模板参数,也可以在调用时给它一个参数。

template <class TYPE_size=int>

thread one(Threader<int>, counter);

【讨论】:

  • 感谢您的帮助,一切顺利。但是为什么当我将 threader 作为非线程函数调用调用时它会起作用。 IE。线程(计数器);。
  • 因为编译器从你的函数参数类型推断模板参数类型。它知道 counter 是什么类型,然后认为“哦,你的意思是写 Threader(counter)”。或多或少。
  • 谢谢。我想我现在明白了,所以当作为线程调用时,Threader 无法从参数“counter”中确定类型,即使它也被传递了。这是因为当 Threader 被称为线程(在这种情况下称为“one”的线程)时,它与它的参数一起作为单独的实体传递,并且编译器由于某种原因无法计算出“计数器”是'Threader' 在创建线程时?
  • 好吧,它与是否从线程调用 Threader 无关。在您的情况下, counter 不是“Threader”函数的参数,它是“one”函数的参数,所以是的:编译器不知道 Threader 实际上是什么函数,或者它的类型。
  • 谢谢科林,非常感谢。
【解决方案2】:

我冒昧地提供各种修复以实现我认为的预期行为:

#include <thread>

template <typename T>
void Threader(T & counter)    // take by reference!
{
   counter++;
}

int main()
{
   unsigned int counter = 100;
   std::thread one(Threader<unsigned int>,   // specify template *instance*
                   std::ref(counter) );      // pass variable as reference
   one.join();
   return counter;
}

【讨论】:

  • +1 表示在原始示例中 counter 不会更改。
【解决方案3】:

您缺少模板的参数列表。

试试:

 unsigned int counter = 100;
 thread one(Threader<unsigned int>,counter);

或者,如果您使用的是 c++x0/c++11 标准,请为您的模板指定一个标准类型,例如:

template <typename TYPE_size = unsigned int>
void Threader(TYPE_size counter)
{
    counter++;
}
int main()
{
    unsigned int counter = 100;
    thread one(Threader<>,counter);
    one.join();    
    cout << counter;
}

【讨论】:

  • 默认参数没有帮助; Threader 始终是模板,而不是函数。
  • 当然参数列表仍然是必需的,调用应该看起来像这样,标准类型:thread one(Threader,counter);或作为简单的函数调用:Threader(counter);
  • 第一个版本确实适用于 c++0x/c++11 标准。我编辑我的答案以使其更清楚。
  • 多么奇怪,我的 GCC 4.6.2 拒绝了它。但是函数模板默认参数在 C++11 中是新的,所以它可能还没有被普遍实现。干杯。
【解决方案4】:

C++11 引入了 lambdas,在这种情况下也可以使用。

基本上,线程是使用 lambda 创建的,其中 lambda 调用函数,然后允许进行模板类型推导。

thread one([counter]() { Threader(counter); });

上面,计数器是按值捕获的,但正如一些答案所暗示的,也可以使用按引用捕获

#include <iostream>
#include <thread>
template <class T>
void Threader(T& counter)
{
    counter++;
}
int main()
{
    unsigned int counter = 100;
    std::thread one([&counter]() { Threader(counter); });
    one.join();    
    std::cout << counter;
}

注意:这个问题被标记为重复,因此添加了使用更新的语言功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多