Question about calling method inside custom IO operator in C++? - io

I have the following code:
#include "iostream"
#include "conio.h"
using namespace std;
class Student {
private:
int no;
public:
Student(){}
int getNo() {
return this->no;
}
friend istream& operator>>(istream& is, Student& s);
friend ostream& operator<<(ostream& os, const Student& s);
};
ostream& operator<<(ostream& os, const Student& s){
os << s.getNo(); // Error here
return os;
}
int main()
{
Student st;
cin >> st;
cout << st;
getch();
return 0;
}
When compiling this code, the compiler produced the error message: "error C2662: 'Student::getNo' : cannot convert 'this' pointer from 'const Student' to 'Student &'"
But if I made the no variable public and change the error line like: os << s.no; then things worked perfectly.
I do not understand why this happened.
Can anyone give me an explanation, please?
Thanks.

Because s is const in that method, but Student::getNo() isn't a const method. It needs to be const.
This is done by changing your code as follows:
int getNo() const {
return this->no;
}
The const in this position means that this entire method does not change the contents of this when it is called.

Related

how to invoke thread without creating static function [duplicate]

I am trying to construct a std::thread with a member function that takes no arguments and returns void. I can't figure out any syntax that works - the compiler complains no matter what. What is the correct way to implement spawn() so that it returns a std::thread that executes test()?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
#include <thread>
#include <iostream>
class bar {
public:
void foo() {
std::cout << "hello from member function" << std::endl;
}
};
int main()
{
std::thread t(&bar::foo, bar());
t.join();
}
EDIT:
Accounting your edit, you have to do it like this:
std::thread spawn() {
return std::thread(&blub::test, this);
}
UPDATE: I want to explain some more points, some of them have also been discussed in the comments.
The syntax described above is defined in terms of the INVOKE definition (§20.8.2.1):
Define INVOKE (f, t1, t2, ..., tN) as follows:
(t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of
type T or a reference to an object of a type derived from T;
((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous
item;
t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a
reference to an object of type T or a reference to an object of a
type derived from T;
(*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item;
f(t1, t2, ..., tN) in all other cases.
Another general fact which I want to point out is that by default the thread constructor will copy all arguments passed to it. The reason for this is that the arguments may need to outlive the calling thread, copying the arguments guarantees that. Instead, if you want to really pass a reference, you can use a std::reference_wrapper created by std::ref.
std::thread (foo, std::ref(arg1));
By doing this, you are promising that you will take care of guaranteeing that the arguments will still exist when the thread operates on them.
Note that all the things mentioned above can also be applied to std::async and std::bind.
Since you are using C++11, lambda-expression is a nice&clean solution.
class blub {
void test() {}
public:
std::thread spawn() {
return std::thread( [this] { this->test(); } );
}
};
since this-> can be omitted, it could be shorten to:
std::thread( [this] { test(); } )
or just (deprecated)
std::thread( [=] { test(); } )
Here is a complete example
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread([=] { member1(); });
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread([=] { member2(arg1, arg2); });
}
};
int main(int argc, char **argv) {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
std::thread tw2 = w->member2Thread("hello", 100);
tw1.join();
tw2.join();
return 0;
}
Compiling with g++ produces the following result
g++ -Wall -std=c++11 hello.cc -o hello -pthread
i am member1
i am member2 and my first arg is (hello) and second arg is (100)
#hop5 and #RnMss suggested to use C++11 lambdas, but if you deal with pointers, you can use them directly:
#include <thread>
#include <iostream>
class CFoo {
public:
int m_i = 0;
void bar() {
++m_i;
}
};
int main() {
CFoo foo;
std::thread t1(&CFoo::bar, &foo);
t1.join();
std::thread t2(&CFoo::bar, &foo);
t2.join();
std::cout << foo.m_i << std::endl;
return 0;
}
outputs
2
Rewritten sample from this answer would be then:
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread(&Wrapper::member1, this);
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread(&Wrapper::member2, this, arg1, arg2);
}
};
int main() {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
tw1.join();
std::thread tw2 = w->member2Thread("hello", 100);
tw2.join();
return 0;
}
Some users have already given their answer and explained it very well.
I would like to add few more things related to thread.
How to work with functor and thread.
Please refer to below example.
The thread will make its own copy of the object while passing the object.
#include<thread>
#include<Windows.h>
#include<iostream>
using namespace std;
class CB
{
public:
CB()
{
cout << "this=" << this << endl;
}
void operator()();
};
void CB::operator()()
{
cout << "this=" << this << endl;
for (int i = 0; i < 5; i++)
{
cout << "CB()=" << i << endl;
Sleep(1000);
}
}
void main()
{
CB obj; // please note the address of obj.
thread t(obj); // here obj will be passed by value
//i.e. thread will make it own local copy of it.
// we can confirm it by matching the address of
//object printed in the constructor
// and address of the obj printed in the function
t.join();
}
Another way of achieving the same thing is like:
void main()
{
thread t((CB()));
t.join();
}
But if you want to pass the object by reference then use the below syntax:
void main()
{
CB obj;
//thread t(obj);
thread t(std::ref(obj));
t.join();
}

Overridden virtual function not called from thread

I am writing a base class to manage threads. The idea is to allow the thread function to be overridden in child class while the base class manages thread life cycle. I ran into a strange behavior which I don't understand - it seems that the virtual function mechanism does not work when the call is made from a thread. To illustrate my problem, I reduced my code to the following:
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(): t(thread(&B::thread_func_non_virt, this)) { }
void join() { t.join(); }
};
struct C : B
{
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // output is "B::thread_func" but "C::thread_func" is expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}
I tried with both Visual studio 2017 and g++ 5.4 (Ubuntu 16) and found the behavior is consistent. Can someone point out where I got wrong?
== UPDATE ==
Based on Igor's answer, I moved the thread creation out of the constructor into a separate method and calling that method after the constructor and got the desired behavior.
Your program exhibits undefined behavior. There's a race on *this between thread_func and C's (implicitly defined) constructor.
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(B*ptr): t(thread(&B::thread_func_non_virt, ptr))
{
}
void join() { t.join(); }
};
struct C:public B
{
C():B(this){}
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // "C::thread_func" is expected as expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}

initializing string in class using constructor

I am creating a class that has two members string and int
I want to use the constructor to initialize both of these two members to use them.
#pragma once
#include <string>
#include <iostream>
using namespace std;
class donation_1
{
public:
//string name;
const char* name;
int donation_amount;
const static size_t string_size = sizeof(string);
const static size_t int_size = sizeof(int);
donation_1(char* name_1 = "Noname", int amount = 0) : name(name_1), donation_amount(amount) {};
};
int main()
{
fstream file;
file.open("donation_total1.txt", ios_base::app);
if (file.is_open())
{
donation_1("xxxx", 20).writedata(file);
donation_1("yyyy", 30).writedata(file);
donation_1("zzzz", 40).writedata(file);
donation_1("MMMM", 50).writedata(file);
donation_1("BBBB", 60).writedata(file);
file.close();
}
else
{
cout << "file couldn't be opened" << endl;
}
return 0;
}
I want to use the constructor to initialize the class variables which I will be using to update a file, however, what I am getting is this error. this error is regarding initializing the string class member.
Severity Code Description Project File Line Suppression State
Error (active) E0310 default argument of type "const char *" is incompatible with parameter of type "char *" Stream_File_Lab D:\INVSPRIVATE\C++\Projects\Stream_File_Lab\donation_1.h 17
The error message is makes it pretty clear. The variable 'name' is declared as const char* but the value being assigned to it is only char* i.e. the const-ness is missing, hence the type incompatibility error throws up.
Please, google for pointer to a const value and how to use them.
Maybe check this tutorial

C++11 std::thread accepting function with rvalue parameter

I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.
Assume following code (I deleted unneeded parts)
template<typename T, typename Task>
class Scheduler
{
private:
typedef std::unordered_map<std::size_t, T> Results;
class Solver
{
public:
Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
{
m_thread.detach();
}
Solver(Solver&& solver) = default; // required for vector::emplace_back
~Solver() = default;
private:
void thread_function(Task&& task)
{
task();
}
std::thread m_thread;
};
public:
Scheduler() = default;
~Scheduler() = default;
void add_task(Task&& task)
{
m_solvers.emplace_back(std::move(task));
}
private:
std::vector<Solver> m_solvers;
};
template<typename T>
struct Ftor
{
explicit Ftor(const T& t) : data(t) { }
T operator()() { std::cout << "Computed" << std::endl; return data; }
T data;
};
int main()
{
Scheduler<int, Ftor<int>> scheduler_ftor;
Scheduler<int, std::function<int(void)>> scheduler_lambda;
Ftor<int> s(5);
scheduler_ftor.add_task(std::move(s));
scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}
Why it doesn't compile?
MVS2015 is complaining about
functional(1195): error C2064: term does not evaluate to a function taking 1 arguments
functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'
While G++ 4.9.2
functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’
functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
I suppose there are some problems with std::moving to std::thread.
If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to
UPDATE
Good discussion here
Start thread with member function
I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode)
lets assume that there is a function int test(int name).
thread t0;
t0 = thread(test,32);
thread t1(test,43);
Passing a argument to function.
int temp = 0;
int testfunc(int& q)
{
cout<<q;
}
thread t1;
t1 = thread(testfunc,ref(temp));
In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void test(int a,int &a,string test)
{
\\do something
}
int main()
{
int test1 = 0;
string tt = "hello";
thread t1;
t1 = thread(23,&test1,tt);
t1.detach();
return 0;
}
if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.

Question about custom I/O operators in C++?

I have the following piece of code:
class Student {
public:
Student(){}
void display() const{}
friend istream& operator>>(istream& is, Student& s){return is;}
friend ostream& operator<<(ostream& os, const Student& s){return os; }
};
int main()
{
Student st;
cin >> st;
cout << st;
getch();
return 0;
}
I have tried myself when omitting the friend keywords to make the operators become the member function of the Student class, then the compiler would produce "binary 'operator >>' has too many parameters". I have read some document saying that happened because all member functions always receive an implicit parameter "this" (that's why all member functions can access private variables).
Based on that explanation, I have tried as follows:
class Student {
public:
Student(){}
void display() const{}
istream& operator>>(istream& is){return is;}
ostream& operator<<(ostream& os){return os; }
};
int main()
{
Student st;
cin >> st;
cout << st;
getch();
return 0;
}
And got the error message: "error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'Student' (or there is no acceptable conversion)"
Can anyone give me a clear explanation, please?
You can't say that the function is a friend function, and then include the function in-line. The friend keyword implies that the function is not defined in the class, but it can access all the private and protected variables of the class. Change your code to:
class Student {
public:
Student(){}
void display() const{}
friend istream& operator>>(istream& is, Student& s);
friend ostream& operator<<(ostream& os, const Student& s);
};
istream& operator >>(istream& is, Student& s) { return is; }
ostream& operator <<(ostream& os, const Student& s) { return os; }
Look at http://www.java2s.com/Code/Cpp/Overload/Overloadstreamoperator.htm for another example.
With << and >>, the left hand operand is always a file stream, so you cannot overload them within your actual class (it'd technically have to go in the file stream class).
I forget where that operator is defined, but it would either be the global operator>>, or the operator belonging to the stream.
Defining it in Student is the wrong place.

Resources