Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将模板参数传递给线程中的模板函数_C++_Templates_C++11 - Fatal编程技术网

C++ 将模板参数传递给线程中的模板函数

C++ 将模板参数传递给线程中的模板函数,c++,templates,c++11,C++,Templates,C++11,我不熟悉模板,所以我决定为我正在编写的一些并发代码编写单元测试,但我似乎无法让它们编译。具体错误是: error C2664: 'std::thread::thread(const std::thread &)' : cannot convert argument 1 from 'void (__cdecl *)(lock &)' to 'void (__cdecl &)(Utility_UnitTests::emptyLock &)' 1>

我不熟悉模板,所以我决定为我正在编写的一些并发代码编写单元测试,但我似乎无法让它们编译。具体错误是:

error C2664: 'std::thread::thread(const std::thread &)' : cannot convert argument 1 from       'void (__cdecl *)(lock &)' to 'void (__cdecl &)(Utility_UnitTests::emptyLock &)'
1>          None of the functions with this name in scope match the target type
1>          w:\code dumpster\utility_unittests\utspinlock.cpp(88) : see reference to function template instantiation 'void Utility_UnitTests::UTSpinLock::lockContension<Utility_UnitTests::emptyLock>(lock &)' being compiled
1>          with
1>          [
1>              lock=Utility_UnitTests::emptyLock
1>          ]
错误C2664:'std::thread::thread(const std::thread&'):无法将参数1从'void(u cdecl*)(lock&')转换为'void(u cdecl&)(Utility_UnitTests::emptyLock&')
1> 作用域中具有此名称的函数都与目标类型不匹配
1> w:\code dumpster\utility\u unittests\utspinlock.cpp(88):请参阅正在编译的函数模板实例化“void utility\u unittests::utspinlock::lockContension(lock&)”的参考
1> 与
1>          [
1> 锁定=实用工具\u单元测试::清空锁定
1>          ]
这个问题在编译器中非常清楚,我没有传递正确的类型,但是我不知道如何修复它!提前谢谢

编辑:我忘了提到,我正在使用Visual Studio 2013

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Utility_UnitTests
{
typedef utils::threading::SpinLock<utils::threading::backoff::empty> emptyLock;
typedef utils::threading::SpinLock<utils::threading::backoff::yield> yieldingLock;
typedef utils::threading::SpinLock<utils::threading::backoff::pause> pausingLock;

TEST_CLASS(UTSpinLock)
{
public:
    template<typename lock>
    void lockAndSleepT(lock &l)
    {
        l.lock();
        std::this_thread::sleep_for(std::chrono::nanoseconds(10));
        l.unlock();
    }

    template<typename lock>
    void lockContension(lock &l)
    {
        std::thread t1(&UTSpinLock::lockAndSleepT<lock>, this, std::ref(l));
        Assert::AreEqual(true, l.isLocked());

        t1.join();
        Assert::AreEqual(false, l.isLocked());
    }

    TEST_METHOD(testLockContension)
    {
        UTSpinLock::lockContension(m_emptySpin);
        UTSpinLock::lockContension(m_yieldingSpin);
        UTSpinLock::lockContension(m_pausingSpin);
    }

    private:
    emptyLock m_emptySpin;
    yieldingLock m_yieldingSpin;
    pausingLock m_pausingSpin;
};
}
使用名称空间Microsoft::VisualStudio::CppUnitTestFramework;
名称空间实用程序单元测试
{
typedef utils::threading::SpinLock emptyLock;
typedef utils::threading::SpinLock yieldingLock;
typedef utils::threading::SpinLock pausingLock;
测试类(UTSpinLock)
{
公众:
模板
无效锁定和休眠(锁定和锁定)
{
l、 锁();
std::this_thread::sleep_for(std::chrono::纳秒(10));
l、 解锁();
}
模板
无效锁定上下文(锁定和锁定)
{
线程t1(&UTSpinLock::lockAndSleepT,this,std::ref(l));
Assert::AreEqual(true,l.isLocked());
t1.join();
Assert::AreEqual(false,l.isLocked());
}
测试方法(testLockContension)
{
UTSpinLock::lockContension(m_emptySpin);
UTSpinLock::lockContension(m_yieldingSpin);
UTSpinLock::lockContension(m_pausingSpin);
}
私人:
emptyLock m_emptySpin;
yieldingLock m_yieldingSpin;
暂停锁定m_暂停销;
};
}

特别感谢WhozCraig!我会接受他的回答,但由于某种原因,我不能。对于那些感兴趣的人,我改变了:

template<typename lock>
void lockContension(lock &l)
{
    std::thread t1(&UTSpinLock::lockAndSleepT<lock>, this, std::ref(l));
    Assert::AreEqual(true, l.isLocked());

    t1.join();
    Assert::AreEqual(false, l.isLocked());
}
模板
无效锁定上下文(锁定和锁定)
{
线程t1(&UTSpinLock::lockAndSleepT,this,std::ref(l));
Assert::AreEqual(true,l.isLocked());
t1.join();
Assert::AreEqual(false,l.isLocked());
}
致:

模板
无效锁定上下文(锁定和锁定)
{
自动绑定=std::bind(&UTSpinLock::lockAndSleepT,this,std::占位符::\u 1);
std::thread t1(有界,std::ref(l));
Assert::AreEqual(true,l.isLocked());
t1.join();
Assert::AreEqual(false,l.isLocked());
}

首先,这肯定是MSVC实现中的一个bug。当
std::thread
的第一个参数是指向成员函数模板的指针时,它似乎遇到了问题。在我的机器上,64位编译器产生相同的错误消息,而32位编译器崩溃。谢天谢地,您可以用很多方法来解决这个问题,所有这些方法都涉及到不直接将指向成员函数模板的指针传递到
线程


选项1-正如您所发现的,创建一个
bind
表达式并将其传递给
thread
是可行的


选项2-重写类,使其成为模板,而成员函数不是模板

template<typename lock>
struct UTSpinLock
{
public:
    void lockAndSleepT(lock &l)
    {}

    void lockContension(lock &l)
    {
        std::thread t1(&UTSpinLock::lockAndSleepT, this, std::ref(l));

        t1.join();
    }
};

选项4-再次不更改类定义,这次将lambda表达式传递给
thread

std::thread t1([&, this](){ lockAndSleepT(l); });

不熟悉CPPFUnit,但单元测试似乎需要一个静态功能;不是成员函数。你有没有试过
std::bind
?你能说得更清楚些吗?“绑定”会去哪里?如果这是一个愚蠢的问题,我很抱歉。我没有(显然)在我的winbox上安装CPPUnit(这不会有任何帮助,因为我在我的Mac上),但是类似于传递
std::bind(&UTSpinLock::lockAndSleepT,this,std::placeholder::\u 1)作为第一个参数,从当前参数列表中删除
this
,以及将锁引用作为第二个参数发送。Sry我手边没有一个盒子可以试一试。顺便说一句,你需要为这个问题加入
。这不是一个愚蠢的问题<代码>标准::绑定
对于除了那些经常使用它的人以外的所有人来说都是绝对神奇的。这就是我的意思。希望它有意义。@WhozCraig。我真的很好奇为什么您的原始代码没有像@n.m.发布的示例那样有效。如果这是因为VC++永远落后于标准遵从性,我不会感到非常震惊,但这似乎很奇怪。不管怎么说,很高兴你有了有效的东西。也许他看到了我没有看到的东西。
std::thread t1(std::mem_fn(&UTSpinLock::lockAndSleepT<lock>), this, std::ref(l));
std::thread t1([&, this](){ lockAndSleepT(l); });