Reputation: 501
I'm converting this code that uses Lewis Baker's cppcoro library to use Boost.Cobalt
#include <cppcoro/generator.hpp>
#include <iostream>
#include <fstream>
#include <string>
cppcoro::generator<std::string> read_script_file(std::ifstream& script)
{
std::string line;
while (std::getline(script, line)) {
if (line.empty()) {
continue;
}
if (line[0] == '#') {
continue;
}
co_yield line;
}
}
void print_script_file()
{
std::ifstream ifs("script");
for (const auto line : read_script_file(ifs)) {
std::cout << line << "\n";
}
}
And this is the Boost.Cobalt version:
#include <boost/cobalt.hpp>
#include <fstream>
#include <iostream>
#include <string>
boost::cobalt::generator<std::string> read_script_file(std::ifstream& script)
{
std::string line;
while (std::getline(script, line)) {
if (line.empty()) {
continue;
}
if (line[0] == '#') {
continue;
}
co_yield line;
}
co_return "--exit";
}
void print_script_file()
{
std::ifstream ifs("script");
while (true) {
const auto line = co_await read_script_file(ifs);
if (line == "--exit") {
break;
}
std::cout << line << "\n";
}
}
The cppcoro version is much more elegant as it doesn't need to return a "--exit" string to finish the generator. Is there a better way to write the Boost.Cobalt version?
[1] cppcoro - https://github.com/lewissbaker/cppcoro
[2] Boost.Cobalt - https://github.com/boostorg/cobalt
Upvotes: 1
Views: 265
Reputation: 501
Answering my own question. Boost.Cobalt author provided a reply [1].
In summary, returning no value from that coroutine is UB (undefined behavior).
This is the final, complete example:
#include <boost/cobalt.hpp>
#include <boost/cobalt/main.hpp>
#include <fstream>
#include <iostream>
#include <string>
boost::cobalt::generator<std::string> read_script_file(std::ifstream& script)
{
std::string line;
while (std::getline(script, line)) {
if (line.empty()) {
continue;
}
if (line[0] == '#') {
continue;
}
co_yield line;
}
co_return {};
}
boost::cobalt::main co_main(int argc, char *argv[])
{
try {
std::ifstream script("script");
if (!script) {
std::cerr << "ERR: failed to open " << argv[1] << "\n";
co_return 1;
}
auto g = read_script_file(script);
while (g) {
const auto line = co_await g;
if (line.empty()) {
break;
}
std::cout << "<" << line << ">\n";
}
}
catch (const std::exception& e) {
std::cout << "Exception: " << e.what() << "\n";
}
co_return 0;
}
[1] https://github.com/boostorg/cobalt/issues/176#issuecomment-2073694105
Upvotes: 1