I was wondering how boost implemented the Lambda library. I was digging into the implementation but it felt like i'm falling down the rabbit hole...
Can someone please explain shortly how the following code snippet works (Taken from here)?
#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
using namespace boost::lambda;
typedef std::istream_iterator<int> in;
std::for_each(
in(std::cin), in(), std::cout << (_1 * 3) << " " );
}
What's going on behind the scenes that creates a functor object that expects an int?
Thanks
Related
So in my code, I've used a method is_empty()in the boost library. I know is_empty has two definitions, one is in the filesystem library of boost:
std::filesystem:is_empty(const std::filesystem::path& p).
And another is in std::integral_constant:
inline constexpr bool is_empty_v = is_empty<T>::value;
I intended to use the one that is in the boost library, but how can I do it? I tried to not do using namespace std at the beginning. Instead, every time I need to cout, I'd use std::cout to avoid the possible ambiguous on my is_empty method. But I still got the same error if I do this. Is there any other way that can resolve this misconception? I attached part of my code snippet below. Thank you!
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "boost/filesystem.hpp"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
...
using namespace boost::filesystem;
using namespace cv;
... inside main() function:
...
directory_iterator itr(param.referFolder);
if( is_empty(itr->path()) )
{
std::cout << "ERROR: ReferenceFolder is empty. Please place reference images inside." << std::endl;
return 1;
}
... ...
for(directory_iterator itr(param.dataFolder); itr != end_itr; ++itr) // search every folder
{
if(is_directory(itr->status()) && !is_empty(itr->path())){
... ...
}
}
So I recently discovered the use of map and vectors, however, I'm having trouble of trying to figure a way to loop through a vector containing strings.
Here's what I've tried:
#include <string>
#include <vector>
#include <stdio>
using namespace std;
void main() {
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t) {
cout<<*t<<endl;
}
}
and when I try to compile it, I get this error:
cd C:\Users\Jason\Desktop\EXB\Win32
wmake -f C:\Users\Jason\Desktop\EXB\Win32\exbint.mk -h -e
wpp386 ..\Source\exbint.cpp -i="C:\WATCOM/h;C:\WATCOM/h/nt" -w4 -e25 -zq -od -d2 -6r -bt=nt -fo=.obj -mf -xs -xr
..\Source\exbint.cpp(59): Error! E157: col(21) left expression must be integral
..\Source\exbint.cpp(59): Note! N717: col(21) left operand type is 'std::ostream watcall (lvalue)'
..\Source\exbint.cpp(59): Note! N718: col(21) right operand type is 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> (lvalue)'
Error(E42): Last command making (C:\Users\Jason\Desktop\EXB\Win32\exbint.obj) returned a bad status
Error(E02): Make execution terminated
Execution complete
I tried the same method using map and it worked. The only difference was I changed the cout line to:
cout<<t->first<<" => "<<t->last<<endl;
Add iostream header file and change stdio to cstdio.
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
using namespace std;
int main()
{
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t)
{
cout<<*t<<endl;
}
return 0;
}
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> data = {"Hello World!", "Goodbye World!"};
for (std::vector<std::string>::iterator t = data.begin(); t != data.end(); t++) {
std::cout << *t << std::endl;
}
return 0;
}
Or with C++11 (or higher):
#include <iostream>
#include <vector>
#include <string>
typedef std::vector<std::string> STRVEC;
int main()
{
STRVEC data = {"Hello World!", "Goodbye World!"};
for (auto &s: data) {
std::cout << s << std::endl;
}
return 0;
}
From the Open Watcom V2 Fork-Wiki on the C++ Library Status page:
<string>
Mostly complete. Although there are no I/O operators, all other member functions and string operations are available.
A workaround (besides implementing the << operator) would be asking the string instances for the C string:
for (vector<string>::iterator t = data.begin(); t != data.end(); ++t) {
cout << t->c_str() << endl;
}
This of course only works as long as the strings don't contain zero byte values.
When I compile your code, I get:
40234801.cpp:3:17: fatal error: stdio: No such file or directory
#include <stdio>
^
You clearly have a header called "stdio" in your include path that you haven't shown us.
If you change that line to the standard #include <iostream>, then the only reported error is that you wrote void main() instead of int main(). Fix that, and it will build and run.
In passing, note also that using namespace should be avoided.
I found a solution to my own issue. Instead of using a c_str, I used std::string and switched to using the G++ compiler instead of Open Watcom
Instead of having:
char *someString="Blah blah blah";
I instead replaced it with:
string someString="Blah blah blah";
This way is much more efficient and easier.
I am using boost spirit qi to parse inbound data then dispatch the correct functionality depending on it's content.
I am using boost::signals to manage the callbacks; my problem is that I don't seem to be able to use phoenix bind with the boost signals.
Consider the following test case:
#include <boost/signals.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(sig, boost::spirit::qi::_1)
]
)
);
}
This doesn't compile, spitting out a wall of errors.
Note that if I replace the phoenix bind line with
boost::phoenix::bind(&f, boost::spirit::qi::_1)
it works as expected (however due to the larger design of the program this isn't possible).
Thanks in advance.
As noted by Igor R. in the comments, your original error was due to the fact that phoenix::bind copies its arguments by default and boost::signals are non-copyable. When you use phoenix::ref to solve that, another error emerges, this one caused by Boost.Phoenix v2's inability to find the returned type. This can also be easily solved by defining BOOST_SPIRIT_USE_PHOENIX_V3.
#include <boost/signals.hpp>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(boost::phoenix::ref(sig), boost::spirit::qi::_1)
]
)
);
}
I have a std::string such as 20040531, I want to format this as 2004.05.31.
Apart from the straight forward way of doing an std::insert at respective locations, is there a better way to do this using Boost?
PS. I cannot use other Boost calls to get date/time as this string is returned via a custom API. So this question is reduced to basic string formatting which may not sound exciting, but I am trying to learn Boost.
You could use boost::format...
#include <string>
#include "boost/format.hpp"
#include <iostream>
int main()
{
std::string a("20040531");
std::cout << boost::format("%1%.%2%.%3%")
% a.substr(0,4) % a.substr(4,2) % a.substr(6,2);
}
You specifically asked about doing this using Boost, but if you wanted to do this in C++ without introducing a dependency on Boost then you could just use a stream to achieve the same thing:
#include <sstream>
#include <string>
#include <iostream>
int main()
{
std::stringstream s;
std::string a("20040531");
s << a.substr(0,4) << '.' << a.substr(4,2) << '.' << a.substr(6,2);
std::cout << s.str();
}
I have a large vector.
The ways that I use multiply the run-time of the program hugely. The first is write all values to a string as they are calculated using stringstreams and later write the string to a file. The other method is to make a long string after the fact and write that to the file. However, both of these are very slow.
Is there a way to just write the vector's values to the text file immediately with line breaks?
Using std::ofstream, std::ostream_iterator and std::copy() is the usual way to do this. Here is an example with std::strings using C++98 syntax (the question was asked pre-C++11):
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> example;
example.push_back("this");
example.push_back("is");
example.push_back("a");
example.push_back("test");
std::ofstream output_file("./example.txt");
std::ostream_iterator<std::string> output_iterator(output_file, "\n");
std::copy(example.begin(), example.end(), output_iterator);
}
[Some years later]
A more modern implementation may look like:
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> example { "This", "is", "a", "test" };
std::ofstream output_file("./example.txt");
std::ostream_iterator<std::string> output_iterator(output_file, "\n");
std::copy(std::begin(example), std::end(example), output_iterator);
}
Assuming you have C++11:
#include <fstream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> v{ "one", "two", "three" };
std::ofstream outFile("my_file.txt");
// the important part
for (const auto &e : v) outFile << e << "\n";
}
Maybe I have missed something, but what is wrong with:
std::ofstream f("somefile.txt");
for(vector<X>::const_iterator i = v.begin(); i != v.end(); ++i) {
f << *i << '\n';
}
That avoids having to do potentially quadratic string concatenation, which I assume is what's killing your run-time.
You can use std::copy and std::ostream_iterator.