std::unique_ptr as parameter to function in std::thread [duplicate] - c++

This question already has answers here:
visual studio implementation of "move semantics" and "rvalue reference"
(2 answers)
Closed 7 years ago.
So I'm trying to pass a std::unique_ptr as a parameter to a function that is launched in a separate thread, and I'm getting a strange error at compile time that reads:
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(1149): error C2280: 'std::unique_ptr<Widget,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
A simplified version of this code, that still reproduces the same issue is:
#include <thread>
#include <memory>
#include <iostream>
class Widget
{
public:
Widget() : m_data(0)
{
}
void prepareData(int i)
{
m_data = i;
}
int getData() const
{
return m_data;
}
private:
int m_data;
};
void processWidget(std::unique_ptr<Widget> widget)
{
std::cout << widget->getData() << std::endl;
}
int main()
{
std::unique_ptr<Widget> widget(new Widget());
widget->prepareData(42);
std::thread t(processWidget, std::move(widget));
t.join();
return 0;
}
My guess is that there is something wrong with the destruction of the Widget object from main(), however I cannot pinpoint the issue. Is it necessary to do something additional to cleanup that variable? By the way, I'm using VS2013.

You are not allowed to make copy of unique_ptr, therefore the copy constructor is disabled. That is pointing the compiler error.
You can fix it with a reference:
void processWidget(std::unique_ptr<Widget>& widget)

Related

std::thread(threadFunction, this); causes error in visual studio, but not visual studio code

So I have the following c++ class which stores a std::thread as a member variable, and starts a member function in that separate thread. However, this code only builds in visual studio code (using msys2 12.1.0 as a G++ compiler), and causes errors when I try to build it in visual studio code.
The line that causes the error seems to be: foo_thread = std::thread(threadFunction, this);
In visual studio code I get a red underline warning saying "no instance of constructor std::thread::thread" matches the argument list", however the code still compiles and runs fine.
In visual studio I get the same error, and a warning "C3867 'Foo::threadFunction': non-standard syntax; use '&' to create a pointer to member", and the code does not compile. When I try foo_thread = std::thread(&threadFunction, this); the error goes away, however when I try to build I get the error "&: illegal operation on bound member function expression. foo_thread = std::thread(&threadFunction, this); does still compile and run on visual studio code however.
How do I make this section work as desired and able to compile across c++ compilers/ides? It is also worth mentioning I don't seem to get these errors when the function that is handed to the newly spawned thread is not a member function, however I need it to be a member function for this program.
Code:
#include <thread>
#include <windows.h>
#include <iostream>
#define DllExport __declspec( dllexport )
typedef void (*funcPtr)(int num);
class Foo {
public:
// Value Constructor
Foo(int a, int b, funcPtr f) {
foo = a;
bar = b;
myFunc = f;
}
int getFoo() { return foo; };
int addBar(int a) { return private_method(a); };
void callMyFunc(int n) { myFunc(n); };
// Start Monitor
void StartThread();
// Stop Monitor
// IsMonitoring()
~Foo() {
if (foo_thread.joinable()) {
foo_thread.join();
}
};
private:
int private_method(int a) { return a + bar; };
int foo;
int bar;
std::thread foo_thread;
void threadFunction();
funcPtr myFunc;
std::atomic<bool> monitoring = ATOMIC_VAR_INIT(false);
};
void Foo::StartThread() {
foo_thread = std::thread(threadFunction, this);
}
void Foo::threadFunction() {
for (int i = 0; i < 10; i++) {
std::cout << "Hello:" << i << std::endl;
Sleep(500);
}
}
I figured it out, proper syntax to make this work is:
foo_thread = std::thread(&Foo::threadFunction, this);

Passing parameters to template constructor [duplicate]

This question already has an answer here:
Why class data members can't be initialized by direct initialization syntax?
(1 answer)
Closed 2 years ago.
In C++ I am having trouble passing parameters to the constructor for a template class.
it works when I instantiate from a function; but if I instantiate from a class, it gives "error C2059: syntax error: 'string'"
this is my very trimmed down example (names have been changed to protect the incent).
I am currently have std:latest enabled in Visual Studio 2019 and I've tried in 2017 as well.
#include <string>
#include <iostream>
template <class T>
class cap
{
public:
cap() : p(new(T)) {}
cap(const std::string& sfile, const std::string& sfunc, int line)
: m_file(sfile), m_func(sfunc), m_line(line) {}
~cap() {
delete p;
std::cout << "object freed: created in " << m_func << " line " << m_line << " of " << m_file;
}
private:
T* p{nullptr};
std::string m_file;
std::string m_func;
int m_line{0};
};
void foo()
{
cap<int> foo1("file", "func", 5); //<< compiles okay
}
class bar
{
cap<int> foo1("file", "func", 5); //<< "syntax error: 'string'"
};
IntelliSense says "expected a type specifier" when I hover the params used inside the class
My end goal is to have a macro to instantiate the object; passing in the location in source.The object thus knows where it was created.
#define CAP(type,var) cap<type> var(__FILE__, __func__, __LINE__)
CAP(somestruct, myvar);
// expands to:
cap<somestruct> myvar("file.cpp", "myfunc", 50);
For in-class initialization use the uniform initialization:
class bar
{
cap<int> foo1{"file", "func", 5};
};
#Alan has already provided a reference for why direct initialization using () don't work. It's also known as the C++ most vexed parse.

How to do c++ multithreading in a class (keep thread ref as member var)

So I am trying do do some multithreading in c++, I am trying to use the std::thread. All examples I can find on the internet use the main method. But I want to create a thread in a class constructor, and join the thread in the destructor and then clean up the thread. I have tried several things like this:
.cpp:
#inlcude "iostream"
myClass::myClass()
{
myThread= new std::thread(threadStartup, 0);
}
myClass::~myClass()
{
myThread->join();
delete myThread;
}
void threadStartup(int threadid)
{
std::cout << "Thread ID: " << threadid << std::endl;
}
.h
#pragma once
#include "thread"
class myClass
{
public:
myClass();
~myClass();
private:
std::thread* myThread;
};
This gives me the following error error: C2065: 'threadStartup': undeclared identifier. I have also tried to add the thread startup method to the class, but that gives me a whole lot more errors.
I cant figure this out, any help would be appreciated.
EDIT: std::thread has been changed to std::thread* like in my code.
If I move the function declaration of threadStartup to the top of my file I get the errors:
Severity Code Description Project File Line Suppression State
Error C2672 'std::invoke': no matching overloaded function found
And
Severity Code Description Project File Line Suppression State
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
Cannot reproduce. Please, see my sample code test-thread.cc:
#include <iostream>
#include <thread>
class MyClass {
private:
std::thread myThread;
public:
MyClass();
~MyClass();
};
void threadStartup(int threadid)
{
std::cout << "Thread ID: " << threadid << std::endl;
}
MyClass::MyClass():
myThread(&threadStartup, 0)
{ }
MyClass::~MyClass()
{
myThread.join();
}
int main()
{
MyClass myClass;
return 0;
}
Tested in cygwin64 on Windows 10 (64 bit):
$ g++ --version
g++ (GCC) 5.4.0
$ g++ -std=c++11 -o test-thread test-thread.cc
$ ./test-thread
Thread ID: 0
$
Please, notice that I don't use new (as its not necessary in this case).
C++ is parsed top down ans since your threadStartup function is declared after you use it, the compiler cannot find it. Declare threadStartup before you use it and you should be ok.

false-positive error using std::functional in vs2015

I have implemented some test functionals yesterday and everything compiled and worked fine without errors. Today i came back to my PC and my std::bind's are underlined red but compile without error. Seems like Intellisense and the compiler do not agree on the std::bind type. How can I fix this?
#include <functional>
class MyClass {
public:
int doE() {
return 0;
}
int doF() {
return 1;
}
};
void main()
{
MyClass obj;
std::function<int()> f = std::bind(&MyClass::doE, obj); // underlined red
std::cout << f();
}
The error message is as follows:
Error (active)
no suitable user-defined conversion from "std::_Binder<std::_Unforced, int (MyClass::*)(), MyClass &>" to "std::function<int ()>" exists
functionals
c:\functionals\functionals\thirdFunctionOnObject.h
I do have the same error type (Intellisense saying there is an error, but it compiles just fine) in more sophisticated code, where I used std::mem_fn().
Had the same problem with VS 2015 C++, I hate it. Microsoft drives me crazy.
For now I am using a nasty work around by moving the code to a static function. In your case it will be similar to the following:
class MyClass {
// other code
int doE () {
return 0;
}
static int statDoE(MyClass * myClass) {
return myClass->doE();
}
}

BOOST_FOREACH: What is the error on using this of a STL container?

Does anyone know why the following generates an error on VC9?
class Elem;
class ElemVec : public vector<Elem>
{
public:
void foo();
};
void ElemVec::foo()
{
BOOST_FOREACH(Elem& elem, *this)
{
// Do something with elem
}
return;
}
The error I get is:
error C2355: 'this' : can only be referenced inside non-static member functions
The only (hack) solution I have right now which compiles without error is:
void ElemVec::foo()
{
ElemVec* This = this;
BOOST_FOREACH(Elem& elem, *This)
{
// Do something with elem
}
return;
}
You shouldn't inherit from STL containers. These are not polymorphic classes and it's the reason BOOST_FORACH can't handle your derived class.
Try to use aggregation instead.
Which compiler/Boost version are you using? I can compile the following without any problem (VS2005/Boost 1.38):
#include <boost/foreach.hpp>
using namespace std;
struct xxx : std::vector<int>
{
void test()
{
BOOST_FOREACH(int x, *this)
{
}
}
};
int main(void) {
xxx x;
x.test();
return 0;
}
Search the Boost bugbase if you want more details.
I had never seen that error. I guess it comes from the implementation of BOOST_FOREACH macro.
May i ask why you're creating a class based on vector<...> and not having a vector member variable ?
EDIT
Following this thread, i found out that this actually is a visual studio bug. The solution you have found seems to be the simplest.
Hmm, all compiled succesfully on my msvc (2005) compiller.
Maybe you have some error, but fixed or avoided it when was created your example.