我昨天发布了一个问题,但是我没有一个可运行的示例来介绍其他用户。现在,我删除了以前的帖子。
当我尝试在类内部制作和使用std::threads()
和std::ref()
时,有些代码无法构建。我不理解所产生的错误消息,它们均以行error: no matching function for call
或error: no type named ‘type’
开头。
如果有问题,我正在使用Clion和CMake。我的文件结构是:
Personal
--include
----main.h
--src
----main.cpp
----CMakeLists.txt
--CMakeLists.txt
CMakeLists.txt
# CMAKE version requirement
cmake_minimum_required(VERSION 3.12)
# Project name
project(scrap CXX)
# Configure the build
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)
add_compile_options(-W -Wall -ggdb)
include_directories(include)
include_directories(${CMAKE_SOURCE_DIR}/include)
# What is being built
add_executable(scrap)
add_subdirectory(src)
# Add external dependencies
find_package(Threads REQUIRED)
target_link_libraries(scrap ${CMAKE_THREAD_LIBS_INIT})
src / CMakeLists.txt
# Add targets
target_sources(scrap PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
main.h
#ifndef PERSONAL_MAIN_H
#define PERSONAL_MAIN_H
#include <future>
#include <iostream>
#include <unistd.h>
class ScrapPaper
{
public:
ScrapPaper();
static void SpinUpThreads();
void ThreadFunction1(std::promise<bool> &prom);
void ThreadFunction2(std::promise<bool> &prom);
private:
};
#endif //PERSONAL_MAIN_H
main.cpp
#include "../include/main.h"
using namespace std;
void ScrapPaper::ThreadFunction1(promise<bool> &prom)
{
cout << "Thread " << this_thread::get_id() << " working in ThreadFunction1!" << endl;
sleep(10);
cout << "Thread " << this_thread::get_id() << " finished sleeping in Function1" << endl;
prom.set_value_at_thread_exit(true);
}
void ScrapPaper::ThreadFunction2(promise<bool> &prom)
{
cout << "Thread " << this_thread::get_id() << " working in ThreadFunction2!" << endl;
sleep(2);
cout << "Thread " << this_thread::get_id() << " finished sleeping in Function2" << endl;
prom.set_value_at_thread_exit(true);
}
void ScrapPaper::SpinUpThreads()
{
promise<bool> promise1;
future<bool> future1 = promise1.get_future();
std::thread (&ScrapPaper::ThreadFunction1, ref(promise1)).detach();
promise<bool> promise2;
future<bool> future2 = promise2.get_future();
std::thread (&ScrapPaper::ThreadFunction2, ref(promise2)).detach();
if (future1.get() && future2.get())
{
cout << "Everything was a-okay" << endl;
}
else
{
cout << "Whoops, there was an error..." << endl;
}
}
int main(int argc, char *argv[])
{
cout << "In Main..." << endl;
ScrapPaper::SpinUpThreads();
} // end main
我遇到的一些错误是:
error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (ScrapPaper::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> > > >::_M_invoke(std::thread::_Invoker<std::tuple<void (ScrapPaper::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> > > >::_Indices)’
operator()()
^~~~~~~~
和
error: no type named ‘type’ in ‘struct std::__invoke_result<void (ScrapPaper::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> > >’
当该类被删除并且只有一个main()
以及ThreadFunction1(...)
和ThreadFunction2(...)
时,代码将生成并运行。我有示波器问题吗?任何建议或帮助,我们将不胜感激!
答案 0 :(得分:2)
使用std::thread
调用成员函数时,第二个参数应该是类的实例(或指向它的指针)。
在您的情况下,代码应为
static ScrapPaper p;
std::thread (&ScrapPaper::ThreadFunction2, p, ref(promise2)).detach();
答案 1 :(得分:2)
这里的问题是,由于您正在使用成员函数,因此需要一个类的实例来调用成员函数。如果SpinUpThreads
不是静态的,则可以使用
std::thread (&ScrapPaper::ThreadFunction1, this, ref(promise1)).detach();
std::thread (&ScrapPaper::ThreadFunction2, this, ref(promise2)).detach();
但是由于它是静态的,因此您必须创建该类的实例以传递给thread
的构造函数。您可以为两个调用共享一个对象,也可以为每个线程分配自己的对象。就像
ScrapPaper common;
std::thread (&ScrapPaper::ThreadFunction1, common, ref(promise1)).detach();
std::thread (&ScrapPaper::ThreadFunction2, common, ref(promise2)).detach();
//or
std::thread (&ScrapPaper::ThreadFunction1, ScrapPaper{}, ref(promise1)).detach();
std::thread (&ScrapPaper::ThreadFunction2, ScrapPaper{}, ref(promise2)).detach();
您还可以使用lambda来简化调用语法。如果您使用lambda,则可以以更自然的方式编写函数调用,看起来像
ScrapPaper common;
std::thread ([&](){ common.ThreadFunction1(promise1); }).detach();
std::thread ([&](){ common.ThreadFunction2(promise2); }).detach();
//or
std::thread ([&](){ ScrapPaper{}.ThreadFunction1(promise1); }).detach();
std::thread ([&](){ ScrapPaper{}.ThreadFunction2(promise2); }).detach();
答案 2 :(得分:2)
您可以执行以下两项操作之一。如所写,这两个线程函数是非静态成员函数。您必须有一个对象来调用它们,这就是其他答案所解决的问题。
但是这些函数都不使用ScrapPaper
对象中的任何数据,因此您可以将它们更改为 static 成员函数,并且其余代码应可以正常工作。也就是说,改变
class ScrapPaper
{
public:
ScrapPaper();
static void SpinUpThreads();
void ThreadFunction1(std::promise<bool> &prom);
void ThreadFunction2(std::promise<bool> &prom);
private:
};
到
class ScrapPaper
{
public:
ScrapPaper();
static void SpinUpThreads();
static void ThreadFunction1(std::promise<bool> &prom);
static void ThreadFunction2(std::promise<bool> &prom);
private:
};
当然,有了这些更改,自然的问题是ScrapPaper
为什么是类,因为它没有数据并且没有对象特定的行为。这暗示可能使ScrapPaper
成为名称空间而不是类。但这是另一个问题的主题。