Are Rvalue members indeed Rvalues too? - c++

They say that members of Rvalues are also Rvalues - which makes a lot of sense. So this is either a VC++-specific bug or a bug in my understanding of Rvalues.
Take this toy code:
#include <vector>
#include <iostream>
using namespace std;
struct MyTypeInner
{
MyTypeInner() {};
~MyTypeInner() { cout << "mt2 dtor" << endl; }
MyTypeInner(const MyTypeInner& other) { cout << "mt2 copy ctor" << endl; }
MyTypeInner(MyTypeInner&& other) { cout << "mt2 move ctor" << endl; }
const MyTypeInner& operator = (const MyTypeInner& other)
{
cout << "mt2 copy =" << endl; return *this;
}
const MyTypeInner& operator = (MyTypeInner&& other)
{
cout << "mt2 move =" << endl; return *this;
}
};
struct MyTypeOuter
{
MyTypeInner mt2;
MyTypeOuter() {};
~MyTypeOuter() { cout << "mt1 dtor" << endl; }
MyTypeOuter(const MyTypeOuter& other) { cout << "mt1 copy ctor" << endl; mt2 = other.mt2; }
MyTypeOuter(MyTypeOuter&& other) { cout << "mt1 move ctor" << endl; mt2 = other.mt2; }
const MyTypeOuter& operator = (const MyTypeOuter& other)
{
cout << "mt1 copy =" << endl; mt2 = other.mt2; return *this;
}
const MyTypeOuter& operator = (MyTypeOuter&& other)
{
cout << "mt1 move =" << endl; mt2 = other.mt2; return *this;
}
};
MyTypeOuter func() { MyTypeOuter mt; return mt; }
int _tmain()
{
MyTypeOuter mt = func();
return 0;
}
This code outputs:
mt1 move ctor
mt2 copy =
mt1 dtor
mt2 dtor
That is, MyTypeOuter's move ctor calls MyTypeInner's copy, not move. If I modify the code to:
MyTypeOuter(MyTypeOuter&& other)
{ cout << "mt1 move ctor" << endl; mt2 = std::move(other.mt2); }
The output is as expected:
mt1 move ctor
mt2 move =
mt1 dtor
mt2 dtor
It seems VC++ (both 2010 and 2013) do not respect this part of the standard. Or am I missing something?

Whether the member of an rvalue is an rvalue or not is not the issue here, because you are dealing with lvalues inside your assignment operator.
In this move assignment operator,
const MyTypeOuter& operator = (MyTypeOuter&& other)
{
cout << "mt1 move =" << endl;
mt2 = other.mt2;
return *this;
}
other is an lvalue (since it has a name), and by extension so is other.mt2. When you say mt2 = other.mt2 you can only invoke the standard assignment operator.
In order to invoke the move constructor, you need to make other.mt2 look like an rvalue, and this is what std::move achieves:
const MyTypeOuter& operator = (MyTypeOuter&& other)
{
cout << "mt1 move =" << endl;
mt2 = std::move(other.mt2);
return *this;
}
See this related question.

Related

Constructing elements of union

The following class outputs when a constructor is called:
class A {
public:
A() {
std::cout << "Default Constructor called at address:" << this << "!\n";
}
A(int val) : val_(val) {
std::cout << "Secondary Constructor called at address:" << this << "\n";
}
A(A&& other) : val_(std::move(other.val_)) {
std::cout << "Move constructor called from " << &other << " to " << this << "\n";
}
A& operator=(A&& other) {
std::cout << "Move assignment called from " << &other << " to " << this << "\n";
val_ = std::move(other.val_);
return *this;
}
private:
int val_;
};
This union allows me to skip the default constructor of A, which is desirable:
union MyUnion {
MyUnion() {}
A a;
};
My goal with main was to move-construct a. Instead it move-assigns the a.
int main(){
MyUnion my_union[2];
std::cout << "Entering for loop:\n";
for (int i = 0; i < 2; ++i){
my_union[i].a = std::move(A(i));
}
return 0;
}
An example output from the above main function is:
Entering for loop:
Secondary Constructor called at address:0x7ffcdd3553a8
Move assignment called from 0x7ffcdd3553a8 to 0x7ffcdd3553b0
Secondary Constructor called at address:0x7ffcdd3553a8
Move assignment called from 0x7ffcdd3553a8 to 0x7ffcdd3553b4
I wanted to move-construct, but I'm instead move-assigning. Move-assigning without move constructing is unsafe in general. The solution I came up with was to use std::construct_at. I also added a destructor. The full program with these modifications is below:
#include <iostream>
#include <memory>
#include <utility>
class A {
public:
A() {
std::cout << "Default Constructor called at address:" << this << "!\n";
}
A(int val) : val_(val) {
std::cout << "Secondary Constructor called at address:" << this << "\n";
}
A(A&& other) : val_(std::move(other.val_)) {
std::cout << "Move constructor called from " << &other << " to " << this << "\n";
}
A& operator=(A&& other) {
std::cout << "Move assignment called from " << &other << " to " << this << "\n";
val_ = std::move(other.val_);
return *this;
}
~A() {
std::cout << "Destructor called at " << this << "\n";
}
private:
int val_;
};
union MyUnion {
MyUnion() {
std::cout << "MyUnion Constructor called!\n";
}
void ConstructAt(A&& other){
std::construct_at(&a, std::forward<A>(other));
}
A a;
~MyUnion(){
std::cout << "MyUnion Destructor called!\n";
a.~A();
}
};
int main(){
MyUnion my_union[2];
std::cout << "\nEntering for loop:\n";
for (int i = 0; i < 2; ++i){
my_union[i].ConstructAt(std::move(A(i)));
}
std::cout << "\nExiting for loop:\n";
return 0;
}
This gives output:
MyUnion Constructor called!
MyUnion Constructor called!
Entering for loop:
Secondary Constructor called at address:0x7ffe38dd4838
Move constructor called from 0x7ffe38dd4838 to 0x7ffe38dd4840
Destructor called at 0x7ffe38dd4838
Secondary Constructor called at address:0x7ffe38dd4838
Move constructor called from 0x7ffe38dd4838 to 0x7ffe38dd4844
Destructor called at 0x7ffe38dd4838
Exiting for loop:
MyUnion Destructor called!
Destructor called at 0x7ffe38dd4844
MyUnion Destructor called!
Destructor called at 0x7ffe38dd4840
This appears to be what I want.
Question
Was this the correct way to call the move constructor? Am I using std::forward correctly? Is this the correct way to handle the destructor of a union?

C++ copy and move constructors with lambda expressions

I've bumped into something strange with C++ copy and move constructors, here when passing to the lambda expression both the copy and move constructors get executed. Strangely though, when I change the declared type of the lambda to auto or use the regular_test function, I get the expected behaviour (copy construction only). Does anyone understand why this is? (tested with both clang and gcc, not msvc)
#include <iostream>
#include <iomanip>
#include <functional>
using namespace std;
struct Test {
inline Test() {
cout << setw(20) << "constructor ";
PrintAddress();
}
Test(const Test&) {
cout << setw(20) << "copy constructor ";
PrintAddress();
}
Test& operator=(const Test&) {
cout << setw(20) << "copy assignment ";
PrintAddress();
return *this;
}
Test(Test&& other) {
cout << setw(20) << "move constructor ";
PrintAddress();
}
Test& operator=(Test&&) {
cout << setw(20) << "move assignment ";
PrintAddress();
return *this;
}
virtual ~Test() {
cout << setw(20) << "destructor ";
PrintAddress();
}
void PrintAddress() {
cout << "Test&: " << this << endl;
}
};
Test regular_test (Test t) {
cout << "regular_test" << endl;
return t;
}
int main() {
cout << "start" << endl;
function<Test(Test)> lambda_test = [] (Test t) {
cout << "lambda_test" << endl;
return t;
};
Test t;
lambda_test(t);
//regular_test(t);
cout << "done" << endl;
return 0;
}
start
constructor Test&: 0x7fffef6faf28
copy constructor Test&: 0x7fffef6faf08
move constructor Test&: 0x7fffef6fade8
lambda_test
move constructor Test&: 0x7fffef6faf10
destructor Test&: 0x7fffef6fade8
destructor Test&: 0x7fffef6faf10
destructor Test&: 0x7fffef6faf08
done
destructor Test&: 0x7fffef6faf28
because std::function::operator() is defined based on the template type of class.
R operator()( Args... args ) const; // Args are parameter of the *class*
so std::function<Test(Test)> would have Test operator()(Test), which would make a copy by itself, then forward to lambda_test (a move)

Move Constructor invoked for a function, but NRVO expected in C++

I don't understand why a move constructor is being invoked during the main function in the code below, specifically the output is:
FString::FString(string one)
FString::FString(string two)
FString::Move Constructor
FString::Move Assign
COMPLETE
So the line I am concerned about is "FString::Move Constructor" - this implies to me that the move constructor is getting invoked in order to fulfill the return statement of the function GetStringTemp(), but from what I understood NRVO should mean that the move constructor should not be invoked. Am I misunderstanding the behaviour of NVRO? Thanks in advance
#include <iostream>
#include <string>
class FString
{
public:
FString(std::string newstring)
: _string(newstring)
{
std::cout << "FString::FString(string "+newstring+")" << std::endl;
}
FString(const FString& rhs)
{
std::cout << "FString::Copy Constructor" << std::endl;
}
FString(FString&& rhs)
{
std::cout << "FString::Move Constructor" << std::endl;
}
FString& operator=(const FString& rhs)
{
std::cout << "FString::Copy Assign" << std::endl;
return *this;
}
FString& operator=(FString&& rhs)
{
std::cout << "FString::Move Assign" << std::endl;
return *this;
}
void Print()
{
std::cout << "Printing: "+_string << std::endl;
}
private:
std::string _string;
};
FString GetTempString()
{
FString temp = FString("two"); // 2: Expected Constructor cout
return temp; // No expected constructor as NVRO assumed
}
int main()
{
FString myString = FString("one"); // 1: Expected Constructor cout
myString = GetTempString(); // 3: Expected Move Assignment cout
std::cout << "COMPLETE" << std::endl;
}

rvalue as initialiser to construct an object

I am new to programming. sorry for my bad english.
I have tried to use rvalue as initialiser to initial objects.
So, according to the code, it would print out what are the used constructor and assignment operator.
But turned out object "what2" and "what3", those don't print out anything.
here is the code:
#include <iostream>
using namespace std;
class X{
public:
int x;
X()= default;
X(int num):x{num}{}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
std::cout << x << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2{a+b};
cout << "---------------" << endl;
X what3 = a+b;
cout << "---------------" << endl;
std::cout << what1.x << std::endl;
std::cout << what2.x << std:: endl;
std::cout <<what3.x << std::endl;
return 0;
}
the output is:
---------------
move assignment
---------------
---------------
---------------
18
18
18
Program ended with exit code: 0
only "what1" uses assignment properly.
so, how can i use rvalue to initial an object? and using operator= to initial an object?
thank you very much.
Your code could result in move operations being used, but your compiler has chosen to elide those moves and allocate the return of operator+ directly at the call site. You can see this happening if you disable copy elision in your compiler (-fno-elide-constructors in GCC or Clang).
Your move constructor and assignment operator will be successfully used in contexts in which copy elision is not permitted, such as this:
X what2 { std::move(what1) }; //can't elide copy, move constructor used
The following code triggers more of your constructors/operators, check it out to see which trigger in what cases
#include <iostream>
using namespace std;
class X{
public:
int x;
X()
{
x = 0;
std::cout << "constructor" << std::endl;
}
X(int num):x{num}
{
std::cout << "list initilizer" << std::endl;
}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
cout << "---------------" << endl;
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2(a+b);
cout << "---------------" << endl;
X what3 = X(a);
cout << "---------------" << endl;
X what4 = X();
cout << "---------------" << endl;
X what5 = std::move(what1);
cout << "---------------" << endl;
what5 = std::move(what1);
cout << "---------------" << endl;
what5 = what1;
cout << "---------------" << endl;
return 0;
}
GCC provides the -fno-elide-constructors option to disable copy-elision. if you want to elide the copy-elision then use flag -fno-elide-constructors. Refer https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization/27916892#27916892 for more detail

C++ Reactor using base & derived classes containing functional objects of different types

I've created this example reactor program to test functionality I wanted to demonstrate.
Essentially the program defines:
Two functional objects to be called on different events.
A base & derived class; the intention of which is to allow different template instantiations of the derived class to be stored as in the same stl container.
A reactor function which uses random numbers to simulate events, then search a container for the matching key and call the functional-object to do its work.
Main does some setup work then calls the reactor function to run in a different thread.
EDIT: Have modified the code so that it now compiles & runs. Apologies, code is now quite long; it started out as a minimal test program. Have added extra sections & lots of print statements to elucidate the functionality. It remains here in case it's of interest to others.
#include <functional>
#include <iostream>
#include <stdlib.h>
#include <chrono>
#include <thread>
#include <unordered_map>
#include <utility>
#include <memory>
class Pollin_Functional_Object
{
public:
//Constructor
Pollin_Functional_Object(const int cnt) : count(cnt)
{
std::cout << "Pollin_Functional_Object: Constructor" << std::endl;
}
//Copy Constructor
Pollin_Functional_Object(const Pollin_Functional_Object &orig) : count(orig.count)
{
std::cout << "Pollin_Functional_Object: Copy Constructor" << std::endl;
}
//Copy assignment
Pollin_Functional_Object& operator= (const Pollin_Functional_Object &that)
{
std::cout << "Pollin_Functional_Object: Copy Assignment Constructor" << std::endl;
if (this != &that)
{
count = that.count;
}
return *this;
}
//Move constructor
Pollin_Functional_Object(Pollin_Functional_Object &&orig) /*noexcept NOT VS2013*/ : count(orig.count)
{
std::cout << "Pollin_Functional_Object: Move Constructor" << std::endl;
}
//Move Assignment
Pollin_Functional_Object& operator=(Pollin_Functional_Object &&that) /*noexcept NOT VS2013*/
{
std::cout << "Pollin_Functional_Object: Move Assignment Constructor" << std::endl;
if (this != &that)
{
count = that.count;
}
return *this;
}
//Operators
bool operator==(const Pollin_Functional_Object &anotherPollin_Functional_Object) const
{
return (count == anotherPollin_Functional_Object.count);
}
void operator()(const int &in) //const
{
std::cout << "Pollin__Functional_Object: operator(" << in << ") Count: " << ++count << std::endl;
}
~Pollin_Functional_Object()
{
std::cout << "Pollin_Functional_Object: Destructor Called." << std::endl;
}
private:
int count;
};
class Pollout_Functional_Object
{
public:
//Constructor
Pollout_Functional_Object(const int count) : count(count)
{
std::cout << "Pollout_Functional_Object: Constructor" << std::endl;
}
//Copy Constructor
Pollout_Functional_Object(const Pollout_Functional_Object &orig) : count(orig.count)
{
std::cout << "Pollout_Functional_Object: Copy Constructor" << std::endl;
}
//Copy assignment
Pollout_Functional_Object& operator= (const Pollout_Functional_Object &that)
{
std::cout << "Pollout_Functional_Object: Copy Assignment Constructor" << std::endl;
if (this != &that)
{
count = that.count;
}
return *this;
}
//Move constructor
Pollout_Functional_Object(Pollout_Functional_Object &&orig) /*noexcept NOT VS2013*/ : count(orig.count)
{
std::cout << "Pollout_Functional_Object: Move Constructor" << std::endl;
}
//Move Assignment
Pollout_Functional_Object& operator=(Pollout_Functional_Object &&that) /*noexcept NOT VS2013*/
{
std::cout << "Pollout_Functional_Object: Move Assignment Constructor" << std::endl;
if (this != &that)
{
count = that.count;
}
return *this;
}
//Operators
bool operator==(const Pollout_Functional_Object &anotherPollout_Functional_Object) const
{
return (count == anotherPollout_Functional_Object.count);
}
void operator()(const int &in) //const
{
std::cout << "Pollout_Functional_Object: operator(" << in << ") Count: " << ++count << std::endl;
}
~Pollout_Functional_Object()
{
std::cout << "Pollout_Functional_Object: Destructor Called." << std::endl;
}
private:
int count;
};
//Needs to be non-templated base class.
class Instruction_Base
{
public:
//Default Constructor
Instruction_Base() = default;
//Constructor
Instruction_Base(const std::string &nme):name(nme)
{
std::cout << "Instruction_Base: Constructor" << std::endl;
}
//Copy Constructor
Instruction_Base(const Instruction_Base &orig) : name(orig.name)
{
std::cout << "Instruction_Base: Copy Constructor" << std::endl;
}
//Copy assignment
Instruction_Base& operator= (const Instruction_Base &that)
{
std::cout << "Instruction_Base: Copy Assignment Constructor" << std::endl;
if (this != &that)
{
name = that.name;
}
return *this;
}
//Move constructor
Instruction_Base(Instruction_Base &&orig) /*noexcept NOT VS2013*/ : name(orig.name)
{
std::cout << "Instruction_Base: Move Constructor" << std::endl;
}
//Move Assignment
Instruction_Base& operator=(Instruction_Base &&that) /*noexcept NOT VS2013*/
{
std::cout << "Instruction_Base: Move Assignment Constructor" << std::endl;
if (this != &that)
{
name = that.name;
}
return *this;
}
virtual ~Instruction_Base()// = default;//dynamic binding. Virtual destructor is necessary in base class even if it does no work.
{
std::cout << "Instruction_Base: Destructor Called" << std::endl;
}
//Operator
bool operator==(const Instruction_Base &anotherInstruction_Base) const
{
return (name == anotherInstruction_Base.name);
}
virtual void callFunctionalObject(const int &in)//marked virtual. Is overridden in derived class Instruction.
{
std::cout << "Instruction_Base: callFunctionalObject(" << in << ")" << std::endl;
}
private:
std::string name;
};
//Derived class; templated. Will store functional-objects of different specified types.
template<typename Functional_Object>
class Instruction : public Instruction_Base //inherits from
{
public:
//Default Constructor
Instruction() = default;
//Constructor
Instruction(const std::string &nme, const std::shared_ptr<Functional_Object> &funcObj) : fo(funcObj)
{
std::cout << "Instruction: Constructor" << std::endl;
}
//Copy Constructor
Instruction(const Instruction &orig) : Instruction_Base(orig), fo(orig.fo)
{
std::cout << "Instruction: Copy Constructor" << std::endl;
}
//Copy assignment
Instruction& operator= (const Instruction &that)
{
std::cout << "Instruction: Copy Assignment Constructor" << std::endl;
Instruction_Base::operator=(that);
if (this != &that)
{
fo = that.fo;
}
return *this;
}
//Move constructor
Instruction(Instruction &&orig) /*noexcept NOT VS2013*/ : Instruction_Base(std::move(orig)), fo(orig.fo)
{
std::cout << "Instruction: Move Constructor" << std::endl;
}
//Move Assignment
Instruction& operator=(Instruction &&that) /*noexcept NOT VS2013*/
{
std::cout << "Instruction: Move Assignment Constructor" << std::endl;
Instruction_Base::operator=(that);
if (this != &that)
{
fo = that.fo;
}
return *this;
}
//Destructor
~Instruction()
{
std::cout << "Instruction: Destructor Called" << std::endl;
}
//Operators
bool operator==(const Instruction_Base &anotherInstruction) const
{
return (name == anotherInstruction.name &&
fo == anotherInstruction.fo);
}
void callFunctionalObject(const int &in) override
{
//std::cout << "Instruction: callFunctionalObject(" << in << ")" << std::endl;
(*fo)(in);
}
private:
std::shared_ptr<Functional_Object> fo;
};
class InstructionsStore
{
public: InstructionsStore()
{
std::cout << "InstructionsStore: Constructor" << std::endl;
}
//Copy Constructor
InstructionsStore(const InstructionsStore &orig) : instructions(orig.instructions)
{
std::cout << "InstructionsStore: Copy Constructor" << std::endl;
}
//Copy assignment
InstructionsStore& operator= (const InstructionsStore &that)
{
std::cout << "InstructionsStore: Copy Assignment Constructor" << std::endl;
if (this != &that)
{
instructions = that.instructions;
}
return *this;
}
//Move constructor
InstructionsStore(InstructionsStore &&orig) /*noexcept NOT VS2013*/ : instructions(orig.instructions)
{
std::cout << "InstructionsStore: Move Constructor" << std::endl;
}
//Move Assignment
InstructionsStore& operator=(InstructionsStore &&that) /*noexcept NOT VS2013*/
{
std::cout << "InstructionsStore: Move Assignment Constructor" << std::endl;
if (this != &that)
{
instructions = that.instructions;
}
return *this;
}
//Operators
bool operator==(const InstructionsStore &anotherInstructionsStore) const
{
return (instructions == anotherInstructionsStore.instructions);
}
//Setter
void addInstruction(const std::string nme, const std::shared_ptr<Instruction_Base> &ib)
{
instructions.insert(std::pair<std::string, std::shared_ptr<Instruction_Base>>(nme, ib));
}
//Getter
std::shared_ptr<Instruction_Base> getInstruction(const std::string nme)//returns pointer to derived Instruction type object
{
auto got = instructions.find(nme);
if (got != instructions.end())
{
//std::cout << "InstructionsStore: getInstruction(" << (got->first).c_str() << ")" << std::endl;
return got->second;
}
}
private:
//Specifying std::shared_ptr<Instruction_Base> base class also allows storage of pointers to types derived
//from Instruction_Base i.e. templated Instruction class objects storing functional-objects of different types.
//Pointers only though, does not work with actual objects.
std::unordered_map<std::string, std::shared_ptr<Instruction_Base>> instructions;
};
//Reactor Function
void reactor(const int &iterations, const std::shared_ptr<InstructionsStore> &is)
{
//Prepare variables
int runLoop(0);
int number(0);
std::string searchFor("");
srand(time(NULL));
while (runLoop < iterations)
{
number = rand() % 100 + 1;//in the range 1 to 100
if (number >= 50)
{
searchFor = "pollin";
}
else
{
searchFor = "pollout";
}
//Find the relevant object
std::shared_ptr<Instruction_Base> ib = is->getInstruction(searchFor);
//Call the functional-object; passes the call via
//the virtual function & dynamic binding in the base class Instruction_Base to
//the overridden derived Instruction class member function.
ib->callFunctionalObject(number);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
++runLoop;
}
}
int main(int argc, char* argv[])
{
//Instantiate the functional-objects and corresponding shared pointers.
std::shared_ptr <Pollin_Functional_Object> spPifo (new Pollin_Functional_Object(0));
std::shared_ptr <Pollout_Functional_Object> spPofo(new Pollout_Functional_Object(0));
//Instantiate the Instruction objects and corresponding shared pointers.
std::shared_ptr <Instruction<Pollin_Functional_Object>> spPiInstr (new Instruction<Pollin_Functional_Object>("pollin", spPifo));
std::shared_ptr <Instruction<Pollout_Functional_Object>> spPoInstr (new Instruction<Pollout_Functional_Object>("pollout", spPofo));
//Instantiate the InstructionsStore object and corresponding shared pointer.
std::shared_ptr<InstructionsStore> spIs(new InstructionsStore);
spIs->addInstruction("pollin", spPiInstr);//add the instruction to the store
spIs->addInstruction("pollout", spPoInstr);//add the instruction to the store
//Then pass the InstructionsStore shared pointer to the reactor function and run.
std::thread t1(reactor, 10, std::cref(spIs));
t1.join();//wait for it.....
return 0;
}
When I try to compile this (g++ --std=c++11 reactor.cpp -pthread) I get a somewhat cryptic
/usr/include/c++/4.9/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<void (*(int, InstructionsStore))(const int&, InstructionsStore&)>’
This appears to be the result of trying to pass stack references to the thread constructor. These are values that are going, by definition, to be copied into the thread object and then passed to the reactor() function. You need to allow these objects to be copied, or dynamically allocate object and pass pointers.
From http://en.cppreference.com/w/cpp/thread/thread/thread:
The arguments to the thread function are copied by value. If a
reference argument needs to be passed to the thread function, it has
to be wrapped (e.g. with std::ref or std::cref).
Keep in mind if you use std::ref, you are still passing this data to another thread, so that will only work if you know that the object you are passing to the other thread will remain alive through the lifetime of the new thread.
If I take out the references in the reactor parameters this compiles fine for me (with a linker error for one of your callFunctionalObject functions not being defined).