To try out the new coroutine feature in boost I created the following program:
#include <boost/coroutine/all.hpp>
#include <string>
#include <vector>
typedef boost::coroutines::coroutine<int(char)> coroutine_t;
void f(coroutine_t::caller_type & ca)
{
std::vector<int> vec = {1, 2, 3};
for (int i : vec)
{
char c = ca.get();
std::cout << "c: " << c << std::endl;
ca(i);
}
}
int main()
{
coroutine_t cr(f);
std::string str("abc");
for (char c : str)
{
std::cout << c << std::flush;
cr(c);
int n = cr.get();
std::cout << n << std::endl;
}
}
The code is based on the sample code from the docs.
My build command goes as follows:
$ g++ -std=c++11 -o test -I/usr/local/include -L/usr/local/lib main.cpp /usr/local/lib/libboost_context.a
Output:
$ ./test
test: /usr/local/include/boost/coroutine/detail/coroutine_get.hpp:43: typename boost::coroutines::detail::param<Result>::type boost::coroutines::detail::coroutine_get<D, Result, arity>::get() const [with D = boost::coroutines::coroutine<char(int), 1>; Result = char; int arity = 1; typename boost::coroutines::detail::param<Result>::type = char]: Assertion `static_cast< D const* >( this)->impl_->result_' failed.
Aborted (core dumped)
The program is aborted due to failed assertion. Can you help me find the error in my code?
I believe you need to add a call ca() at the beginning of your function f.
From the boost documentation:
The execution control is transferred to coroutine at construction (coroutine-function entered) - when control should be returned to the original calling routine, invoke boost::coroutines::coroutine<>::operator() on the first argument of type boost::coroutines::coroutine<>::caller_type inside coroutine-function.
Related
I am trying to convert std::string_view to float without an intermediate conversion to std::string (which will cause extra heap allocation) with a C++20 compiler.
#include <iostream>
#include <charconv>
int main() {
std::string_view s = "123.4";
float x;
std::from_chars(s.data(), s.data() + s.size(), x);
std::cout << x << std::endl;
}
But I am unable to compile this code:
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
What I am doing wrong?
GCC's C++ standard library implementation first supported std::from_chars for float in GCC 11.1. 10.x won't support it.
Since you're not checking for success, and you know your string is null-terminated, you can use atof() instead, which is similarly unsafe. If you want proper checking for parsing errors, use strtof, which will give you similar information to from_chars as to whether the input matched properly:
#include <iostream>
#include <cstdlib>
int main() {
std::string_view s = "123.4";
char * end;
float x = std::strtof(s.data(), &end);
if (end != s.data() + s.size())
{
std::cout << "Parse error";
}
else
{
std::cout << x << std::endl;
}
}
If and only if you know that your string view is null terminated, you can use this
float x = static_cast<float>(atof(s.data()));
Look into charconv header. For example GCC have next guard in it
#if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE
So it can be not implemented, or your compiler not configured to use at least C++ 17 standard. I.e. no -std=c++20 for GCC and Clang or /std:c++latest for Microsoft VC++ command line options passed to your compiler, or your implementation i.e. port not implementing this functionality and not fully implement a standard.
You always can replace from_chars with strtof c function.
For example:
#include <iostream>
#include <string_view>
#include <system_error>
#include <cmath>
#include <charconv>
#include <cstdlib>
int main(int argc, const char** argv)
{
std::string_view sv("12.345678");
#ifdef __cpp_lib_to_chars
float result = NAN;
auto conv_ret = std::from_chars(sv.data(), (sv.data() + sv.size()), result);
std::error_code ec = std::make_error_code(conv_ret.ec);
#else
char *endp = nullptr;
float result = std::strtof(sv.data(), &endp);
std::error_code ec;
if (errno == ERANGE) {
ec = std::make_error_code(std::errc::result_out_of_range);
}
#endif
if(ec) {
std::cerr << ec.message() << std::endl;
return ec.value();
}
std::cout << "Float: " << result << std::endl;
return 0;
}
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
Tried following code based on above error:
#if defined(CYGWIN_NT) || defined(AIX71) || defined(SUNOS)
#include <iostream>
using namespace std;
#elif defined(LINUX) || defined(HPUX11)
#include <iostream.h>
#else
#error handle iostream/iostream.h error.
#endif
#include <charconv>
int main()
{
string_view s = "123.4";
// Always better to initialize.
float x = 0.0f;
from_chars(s.data(), s.data() + s.size(), x);
cout << x << endl;
return 0;
}
// Sample compilation:
// echo g++ -Wall 73333331.cpp -D$(uname -s | sed "s/-[0-9].*.[0-9].*-[0-9].*//;") -std=c++20 -o ./a.out
// g++ -Wall 73333331.cpp -DCYGWIN_NT -std=c++20 -o ./a.out
// ./a.out
// 123.4
I'm trying to use the function norm_2_vector from boost.
But I'm getting the error ‘norm_2_square’ was not declared in this scope.
To compile I used the command below, where testNormSquare is the name of the program:
g++ -o testNorm2Square testNorm2Square.cpp
Question: Is there anything I'm missing? What should I do to make the code compilable?
A toy example that is not working is given below.
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
vector<double> v (3);
for (unsigned i = 0; i < v.size (); ++ i)
v(i) = i;
std::cout << 2.0 * v << std::endl;
std::cout << v * 2.0 << std::endl;
std::cout << norm_2_square(v);
}
The error message is the following:
testNorm2Square.cpp:12:18: error: ‘norm_2_square’ was not declared in this scope
Another problem happens if I specify explicitly that norm_2_square belongs to boost::numeric::ublas:
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
vector<double> v (3);
for (unsigned i = 0; i < v.size (); ++ i)
v(i) = i;
std::cout << 2.0 * v << std::endl;
std::cout << v * 2.0 << std::endl;
std::cout << boost::numeric::ublas::norm_2_square(v);
}
In this case the error message is:
testNorm2SquareV2.cpp:12:41: error: ‘norm_2_square’ is not a member of ‘boost::numeric::ublas’
I need to import a function from a Linux .so library with boost.dll library. My code is like this:
namespace n1 {
namespace n2 {
struct st {
std::string n;
int m;
}
}
}
void foo(std::string const&, n1::n2::st& attr) {
/*some implementation*/
}
Here I try to import the function foo():
int main(int argc, char** argv) {
boost::filesystem::path path("some path");
boost::dll::experimental::smart_library lib(path);
auto f2 = lib.get_function<void(std::string const&, n1::n2::st&)>(path, "n1::n2::foo"); //<<----here runtime error
f2( std::string(), st{});
}
but I get this runtime error:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl >'
what(): boost::dll::shared_library::get() failed (dlerror system message: /path_to_my_library.so: undefined symbol: n1::n2::foo): Illegal seek
Because n1::n2::foo is not a C-compatible export name, I'd suggest you need either to use the mangled name, or use mangled_import
Caution: This feature is experimental
On my compiler
foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, n1::n2::st&)
mangles to
_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE
On the topic of also importing the struct, see Class Imports
UPDATE
A working sample based on the manual mangling approach:
shared.cpp
#include "shared.h"
#include <iostream>
void foo(std::string const& msg, n1::n2::st& attr) {
std::cout << msg << " from " << __FILE__ << ":" << __LINE__ << " (" << __PRETTY_FUNCTION__ << ")\n";
std::cout << "attr.m = " << attr.m << "\n";
std::cout << "attr.n = " << attr.n << "\n";
}
shared.h
#include <string>
namespace n1 { namespace n2 { struct st { std::string n; int m; }; } }
main.cpp
#include <boost/dll.hpp>
#include <boost/dll/smart_library.hpp>
#include <boost/dll/import_mangled.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include "shared.h"
int main() {
boost::filesystem::path path("./libshared.so");
try {
boost::dll::experimental::smart_library lib(path);
//auto f1 = boost::dll::experimental::import_mangled<void(std::string const&, n1::n2::st&)>(path, "foo");
auto f1 = boost::dll::import<void(std::string const&, n1::n2::st&)>(path, "_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE");
n1::n2::st arg { "world", 42 };
f1("hello", arg);
} catch(boost::exception const& e) {
std::cout << boost::diagnostic_information(e, true) << '\n';
}
}
See it Live On Coliru
Compiled with:
g++ -std=c++14 -shared -fPIC shared.cpp -o libshared.so
g++ -std=c++14 main.cpp -ldl -lboost_system -lboost_filesystem
Show the mangled names with
nm libshared.so
Run the demo with
./a.out
Prints
hello from shared.cpp:5 (void foo(const string&, n1::n2::st&))
attr.m = 42
attr.n = world
Using C++11 std::async in this snippet:
int foo()
{
::sleep(2);
return 123;
}
int main()
{
future<int> r1(async(foo));
int r2 = foo();
cout << r1.get() + r2 << endl;
return 0;
}
It produces the right result, but runs both foo's serially (whole app runs 4 seconds). Compiled as:
g++ -std=gnu++11 -O2 foo.cc -lpthread (Ubuntu 12.10 64bit, gcc 4.7.2)
You might need to add a launch policy of std::launch::async:
std::async(std::launch::async, foo);
std::future has been criticized e.g. in this CppCon presentation for being slow. You can avoid std::async and std:future entirely by using this header-only library. You can run any number of functions asynchronously and get the results as a tuple. Also exceptions can be caught normally.
Here is an example:
#include <iostream>
#include "Lazy.h"
template <class T>
T foo(T x) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return x + 10.5;
}
int main() {
int input = 54;
try {
auto [i, d, c] = Lazy::runParallel(
[&](){ return foo(int(input)); },
[&](){ return foo(double(input)); },
[&](){ return foo(char(input)); } );
std::cout << "foo(int) = " << i << ", foo(double) = " << d << ", foo(char) = " << c << '\n';
}
catch (...) {
// Deal with the exception here
}
}
/* Output:
foo(int) = 64, foo(double) = 64.5, foo(char) = #
*/
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Float to binary in C++
I want to print out the binary representation of a float number in C++. Not very practical, just out of curiosity.
The following program doesn't compile though. The reinterpret_cast fails. What kind of cast can I use so that I can do the " &(1 << i) " part?
#include <iostream>
using namespace std;
void toBinary(float num) {
int numi = reinterpret_cast<int>(num);
cout << num << " " << numi << endl;
for (int i = 0; i < 8 * sizeof(num); i++){
if (numi & (1<<i)) {
cout << 1;
} else {
cout << 0;
}
}
cout << endl << endl;
}
int main() {
float a;
cout << sizeof(int) << " " << sizeof(float) << endl;
a = 13.5;
toBinary(a);
toBinary(13.9);
toBinary(2 * a);
toBinary(-a);
}
There's a much easier way. Take a pointer to the float, and reinterpret_cast it to a pointer to char. Now loop through sizeof(float) and convert each char to 8 binary digits. This method works for doubles too.
Use a union. I did this code to do exactly what you want:
// file floattobinary.cc
#include <string>
#include <inttypes.h> // for uint32_t
using namespace std;
void floatToBinary(float f, string& str)
{
union { float f; uint32_t i; } u;
u.f = f;
str.clear();
for (int i = 0; i < 32; i++)
{
if (u.i % 2) str.push_back('1');
else str.push_back('0');
u.i >>= 1;
}
// Reverse the string since now it's backwards
string temp(str.rbegin(), str.rend());
str = temp;
}
Below is a test program to run this function:
// file test.cc
#include <iostream>
#include <string>
#include <cstdlib> // for atof(3)
using namespace std;
void floatToBinary(float, string&);
int main(int argc, const char* argv[])
{
string str;
float f;
if (argc > 1)
{
f = static_cast<float>(atof(argv[1]));
floatToBinary(f, str);
}
cout << str << endl;
return 0;
}
Compile and run (I'm using GNU g++ on Linux):
me#mypc:~/college/c++/utils$ g++ -c floattobinary.cc
me#mypc:~/college/c++/utils$ g++ -c test.cc
me#mypc:~/college/c++/utils$ g++ -o test *.o
me#mypc:~/college/c++/utils$ ls
floattobinary.cc floattobinary.o test* test.cc test.o
me#mypc:~/college/c++/utils$ ./test 37.73
01000010000101101110101110000101
me#mypc:~/college/c++/utils$ ./test 2.0
01000000000000000000000000000000
me#mypc:~/college/c++/utils$ ./test 0.0
00000000000000000000000000000000
me#mypc:~/college/c++/utils$ ./test 237.74
01000011011011011011110101110001
me#mypc:~/college/c++/utils$ ./test 2.74e12
01010100000111110111110100101111
me#mypc:~/college/c++/utils$ ./test 2.74e13
01010101110001110101110001111010
me#mypc:~/college/c++/utils$ ./test -88.37
11000010101100001011110101110001