I am learning how to use boost coroutines2 library. I have read some tutorials and started experimenting with it. But then I found something very confusing. Please take a look at this basic example.
#include <boost/coroutine2/all.hpp>
#include <iostream>
using namespace std;
typedef boost::coroutines2::coroutine<int> cr;
void creator(cr::push_type& yield)
{
cout << "First time." << endl;
yield(1);
cout << "Second time. " << endl;
yield(2);
}
int main()
{
cr::pull_type source{creator};
source();
}
The result is, naturally, this:
First time.
Second time.
But, to my surprise, when I remove the 'source' call in the main function, the result is just the same! (According to tutorials, the coroutine is called first time at construction time, so it is ok that it is called, but should be now called only once!)
#include <boost/coroutine2/all.hpp>
#include <iostream>
using namespace std;
typedef boost::coroutines2::coroutine<int> cr;
void creator(cr::push_type& yield)
{
cout << "First time." << endl;
yield(1);
cout << "Second time. " << endl;
yield(2);
}
int main()
{
cr::pull_type source{creator};
}
The result is still:
First time.
Second time.
When I remove the second 'yield' in the coroutine, the result is also the same:
#include <boost/coroutine2/all.hpp>
#include <iostream>
using namespace std;
typedef boost::coroutines2::coroutine<int> cr;
void creator(cr::push_type& yield)
{
cout << "First time." << endl;
yield(1);
cout << "Second time. " << endl;
}
int main()
{
cr::pull_type source{creator};
}
Result:
First time.
Second time.
How is that possible? How does it work? I expected that when I don't call the coroutine, then even if there is another 'yield' waiting, nothing will happen.
And I find also strange this behaviour:
When I add another 'source' statements in the main, the code still prints the same, as at the beginning!
#include <boost/coroutine2/all.hpp>
#include <iostream>
using namespace std;
typedef boost::coroutines2::coroutine<int> cr;
void creator(cr::push_type& yield)
{
cout << "First time." << endl;
yield(1);
cout << "Second time. " << endl;
yield(2);
}
int main()
{
cr::pull_type source{creator};
source();
source();
}
Result:
First time.
Second time.
No error, even when sourcing more times than there are 'yield's.
Only after adding one more 'source' in the main function do I receive a runtime error (This application has requested the Runtime to terminate it in an unusual way...)
int main()
{
cr::pull_type source{creator};
source();
source();
source();
}
Could someone help me please with understanding this behaviour?
The reason lies in a bug in Boost. I checked that in Boost 1.65.1 everything works fine. Here is the proof: https://wandbox.org/permlink/pRuSgnwa3VPdqNUk
Related
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
void getAnswer(std::vector<std::string> &answers, int nAnswers)
{
int index = rand() % nAnswers;
}
int main()
{
std::vector<string> answers;
answers.push_back("Most Certainly");
answers.push_back("Absolutely");
answers.push_back("Yes");
answers.push_back("You Can Bet On It");
answers.push_back("Odds look good");
answers.push_back("Let's talk about that some other time");
answers.push_back("Odds don't look so good");
answers.push_back("I think you know the answer to that question");
answers.push_back("I don't think I'm qualified to answer that question");
answers.push_back("Absolutely Not");
answers.push_back("I Don't Think So");
answers.push_back("Um...no");
std::vector<string> qAnswers(answers);
answers.size();
string questionAsked;
bool pgExit = false;
srand((unsigned int)time(NULL));
cout << "\nWelcome to the Magic 8Ball.\n";
cout << "\nAsk a question and I will predict the answer!\n" << endl;
//loop and ask the user to enter a question or enter "x" to stop
while (!pgExit) {
cout << "What is your question? (Type question or Enter 'x' to exit) " << endl;
//use getline to get the question
getline(cin, questionAsked);
//call getAnswer with your array and number of possible answers to get an answer
getAnswer(answers, answers.size());
//output the answer
if (questionAsked.compare("x") == 0)
{
cout << "Maybe next time. Have a good day.";
pgExit = true;
}
if (questionAsked.compare("") != 0 && questionAsked.compare("x") != 0)
{
getAnswer;
std::cout << getAnswer(answers, answers.size()) << std::endl;
}
}
}
The issue I am having is when I compile, it is saying 'no operator matches "<<" these operands. Standard operands are: std::ostream << void'
I am not sure I understand. I am passing the vector string and the vector size to void getAnswers to get the randomize for the answers. What am I missing?
Any help is greatly appreciated.
void getAnswer(std::vector<std::string> &answers, int nAnswers)
The void return "type" states explicitly that this function returns nothing so you cannot then go and attempt to use that return value in an expression:
std::cout << getAnswer(answers, answers.size()) << std::endl;
Assuming that you will eventually return a random answer from your list of answers (based on code to date), the first thing you should do is dummy up a reurn value:
std::string getAnswer(std::vector<std::string> &answers, int nAnswers)
{
// Just return last one for now (make sure you
// have at least one in the collection).
return answers[nAnswers - 1];
}
Then you can later adapt it to provide a random one. I could have just provided the complete function but, since this is probably educational work, you'll learn a lot more by doing this yourself (this answer is just to get you over your specific problem).
I have included some sample code at the bottom for you to look over (and for future readers who may not be doing the classwork) but I urge you to try yourself first.
As an aside, you should also be aware that you have some rather superfluous lines in your code, specifically:
answers.size();
getAnswer(answers, answers.size());
getAnswer;
None of these do anything useful, they simply evaluate the expression and throw away the result.
I'm also not why you attempt to create a second vector from the original, especially since you don't use it anywhere:
std::vector<string> qAnswers(answers);
As mentioned earlier, my sample code follows. Please do not use it verbatim if you value your marks (or integrity) - any educator worth their salt will be using plagiarism detection tools:
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
// Anon namespace to hide this in translation unit.
namespace {
// No need to pass in size, vector has this.
const std::string &getAnswer(const std::vector<std::string>answers) {
return answers[std::rand() % answers.size()];
}
};
int main() {
srand(static_cast<unsigned int>(time(nullptr)));
// Can be const if initialised rather than each entry pushed.
const std::vector<std::string> answers = {
"Most Certainly", "Absolutely", "Yes", "You Can Bet On It",
"Odds look good", "Let's talk about that some other time",
"Odds don't look so good",
"I think you know the answer to that question",
"I don't think I'm qualified to answer that question",
"Absolutely Not", "I Don't Think So", "Um...no",
};
std::cout << "\nWelcome to the Magic 8Ball.\n";
std::cout << "\nAsk a question and I will predict the answer!\n";
// Infinite loop, use break to exit.
while (true) {
// Ask and get response.
std::cout << "\nWhat is your question (x to exit)? " << std::endl;
std::string questionAsked;
std::getline(std::cin, questionAsked);
// Exit loop if told so.
if (questionAsked == "x") {
std::cout << "Maybe next time. Have a good day.\n\n";
break;
}
// Answer any non-blank question.
if (! questionAsked.empty()) {
std::cout << getAnswer(answers) << '\n';
}
}
}
I was trying out some c++11 code, and I tried to write a program that counts down from 10, sleeping in between the outputs. Here's what I have so far:
#include <iostream>
using namespace std;
#include <chrono>
#include <thread>
void Sleep(int x)
{
std::this_thread::sleep_for(std::chrono::duration<int>(x));
}
int main()
{
for (int x=10; x>0; x--) {
cout << x << "...";
Sleep(1);
}
cout << " FIRE!!\n";
}
The problem is, this code waits 10 seconds and then prints all of the output, instead of counting down from 10. How come this is? And how can I fix it?
(By the way, I tried this on a computer running Linux Mint 17 and MacOSX 10.9, and both times I got the same result)
Probably because you don't flush the output. Try this
cout << x << "..." << flush;
Stream output can be buffered, which means the results don't always appear immediately. Flushing at least increases the chance that you will see some output immediately.
You need to flush the output each time round the loop, otherwise the runtime system will wait for the buffer to be full or (sometimes) an end of line to be sent.
Also, when using std::chrono::duration<> it is better to use one of the explicitly defined types if possible for readability. In this case you are measuring times in seconds so I used std::chrono::seconds in your example:
#include <iostream>
using namespace std;
#include <chrono>
#include <thread>
void Sleep(int x)
{
// better to use explicit types for duration
// for readability
std::this_thread::sleep_for(std::chrono::seconds(x));
}
int main()
{
for(int x = 10; x > 0; x--) {
cout << x << "..." << std::flush; // need to flush here
Sleep(1);
}
cout << " FIRE!!\n";
}
I have a vector of vectors, and I want to connect them one by one to form a long vector. This could be done by inserting at the end. Inspired by this question, I was thinking that using make_move_iterator would replace copy with move and thus would be more efficient. But the following test demonstrates that make_move_iterator will cause a larger time consumption.
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
using namespace std;
int main()
{
string a = "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongstring";
vector<string> b(10,a);
vector<vector<string> > c(1000,b);
vector<string> d,e;
auto t1 = chrono::system_clock::now();
for(auto& item : c)
{
d.insert(d.end(),item.begin(),item.end());
}
cout << c[0][0].length() << endl;
auto t2 = chrono::system_clock::now();
for(auto& item:c)
{
e.insert(e.end(), std::make_move_iterator(item.begin()),std::make_move_iterator(item.end()));
}
auto t3 = chrono::system_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(t2-t1).count() << endl;
cout << chrono::duration_cast<chrono::nanoseconds>(t3-t2).count() << endl;
cout << c[0][0].length() << endl;
cout << "To check that c has been moved from." <<endl;
}
//Output:
//122
//1212000
//1630000
//0
//To check that c has been moved from.
Thus I'm wondering, does this approach really help improve efficiency?
The test in the question description was conducted on cpp shell
I later tried on ideone and it turned out that make_move_iterator is obviously more efficient. So it seems to be a compiler-dependent thing.
122
320576
98434
0
To check that c has been moved from.
Can anyone share an example of RabinMillerTest() that works? My googlefu is sadly lacking.
Here is my test code:
#include "integer.h"
#include "nbtheory.h"
#include "cryptlib.h"
#include "osrng.h"
#include <iostream>
int main(int argc,char *argv[])
{
CryptoPP::RandomNumberGenerator rng;
CryptoPP::Integer a("123456789");
CryptoPP::Integer b;
std::cout << a << std::endl;
std::cout << "is prime: " << IsPrime(a) << std::endl;
b=a+CryptoPP::Integer::Two();
std::cout << b << std::endl;
std::cout << "is prime: " << IsPrime(b) << std::endl;
int r=RabinMillerTest(rng,&b,2);
std::cout << "RabinMiller: " << r <<std::endl;
}
Here is the build command:
g++ bignum.cpp -I. -fpermissive libcryptopp.a
The only example I could find is here:
http://www.cryptopp.com/wiki/Diffie-Hellman
My code crashes every time I run it, and one crash was so bad I had to cold boot to recover. If I remove the call to RabinMillerTest() then it runs fine. I suspect a problem with C++ syntax is the culprit, but I just don't see it. Since I can't use it properly, I am currently stripping the guts of the RabinMillerTest() function to use separately.
You're using the wrong signature for MillerRabinTest. Here's what it is (from nbtheory.h):
CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng,
const Integer &w, unsigned int rounds);
Instead of:
int r=RabinMillerTest(rng,&b,2);
Try:
bool b=RabinMillerTest(rng, b, 2);
There's also a discussion of Miller-Rabin round counts on the Cryptography Stack Exchange at Trial divisions before Miller-Rabin checks?. It was written with OpenSSL and Crypto++ in mind.
This was the answer edited into the question. Adding as a separate answer block. Credit goes to user3920315.
UPDATE: I got it to work. Here is the working code:
#include "integer.h"
#include "nbtheory.h"
#include "cryptlib.h"
#include "osrng.h"
#include <iostream>
int main(int argc,char *argv[])
{
//CryptoPP::RandomNumberGenerator rng;
CryptoPP::NonblockingRng rng;
CryptoPP::Integer a("123456789");
CryptoPP::Integer b;
std::cout << a << std::endl;
std::cout << "is prime: " << IsPrime(a) << std::endl;
b=a+CryptoPP::Integer::Two();
std::cout << b << std::endl;
std::cout << "is prime: " << IsPrime(b) << std::endl;
bool r=RabinMillerTest(rng,b,2);
std::cout << "RabinMiller: " << r <<std::endl;
}
I changed the call to RabinMillerTest() but the resulting executable would still crash.
When I changed the random number generator to a class that inherits from RandomNumberGenerator, then it works.
I have a simple test program in C++ that prints out attributes of a circle
#include <iostream>
#include <stdlib.h>
#include "circle.h" // contains the Circle class
using namespace std;
void print_circle_attributes(float r) {
Circle* c = new Circle(r);
cout << "radius: " << c->get_radius() << endl;
cout << "diameter: " << c->get_diameter() << endl;
cout << "area: " << c->get_area() << endl;
cout << "circumference: " << c->get_circumference() << endl;
cout << endl;
delete c;
}
int main(int argc, const char* argv[]) {
float input = atof(argv[0]);
print_circle_attributes(input);
return 0;
}
when I run my program with the parameter 2.4 it outputs:
radius: 0.0
diameter: 0.0
area: 0.0
circumference: 0.0
I've previously tested the program without the parameter, but simply using static values, and it ran just fine; so I know there's nothing wrong with the class I made...
So what did I do wrong here?
argv[0] is the program name. You want argv[1] for the first argument.
Also, check that argc is at least two before trying to access it. You might also consider std::stoi, std::istringstream or strtod rather than atoi for conversion, since they can detect bogus input.
Finally, why are using new when an automatic variable will suffice? You should get out of that habit straight away, or spend the rest of eternity debugging memory leaks.
argv[0] is the name of the executable being invoked.
Your first command line parameter will be in argv[1].
To make sure that your program does not silently fail again, you should check how many parameters you actually have and if the atof returns a value, and show a message to the user explaining the issue accordingly.