Unexpected results from boost::lexical_cast<int> with boost::iterator_range - c++

I tried converting a substring (expressed by a pair of iterators) to an integer by boost::lexical_cast:
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
// assume [first, last) as substring
const std::string s("80");
auto first = s.begin(), last = s.end();
std::cout << boost::lexical_cast<int>(boost::make_iterator_range(first, last)) << std::endl;
return 0;
}
Output: (wandbox)
1
I got expected result (80) by workaround: boost::make_iterator_range(&*first, last - first).
Question: Why above code does not work as expected? And, where does 1 come from?
lexical_cast does not support iterator_range<std::string::(const_)iterator>
misuse of lexical_cast or iterator_range
bugs of lexical_cast or iterator_range
some other reason

The short answer is number 2 from your list, misuse of iterator_range - specifically you're using it without explicitly including the proper header for it.
Adding this:
#include <boost/range/iterator_range.hpp>
will make it behave as you expect.
The iterator_range and related functionality is split into two headers, iterator_range_core.hpp and iterator_range_io.hpp. The first one contains the class definition, the second one contains, among other things, the operator<< overload which makes it streamable and so usable by lexical_cast (usable in the sense that it will actually work as you expect).
Because you didn't included the proper header, you should normally get a compiler error, but in this case you're not getting it because lexical_cast.hpp includes the first of those two headers, iterator_range_core.hpp. This makes everything build fine, but it doesn't get the operator<< from the second header. Without that overload, when lexical_cast writes the range to the stream to perform the conversion, the best overload it finds is the one taking a bool parameter (because iterator_range has a default conversion to bool). That's why you're seeing that 1, because it's actually writing true to the underlying conversion stream.
You can test this easily with something like this:
auto someRange = boost::make_iterator_range(first, last);
std::cout << std::boolalpha<< someRange;
Without #include <boost/range/iterator_range.hpp> this will print true, with that include it will print your string (80).

Related

Can reverse iterators be used in place of forward iterator parameters?

Looking at the function parameters for std::generate() the parameters say that this function only takes forward iterators:
I'm having a hard time understanding why this code is compiling:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void printer(int i) {
cout << i << ", ";
}
struct Sequence {
int start;
Sequence(int start) :start(start) {
}
int operator() () {
return start++ % 7;
}
};
int main() {
vector<int> v1(4);
generate(v1.rbegin(), v1.rend(), Sequence(10)); // Line I
for_each(v1.begin(), v1.end(), printer);
}
Outputs 6, 5, 4, 3,
My understanding is that std::generate takes two parameters that need to both be forward iterators.
And looking at the documentation for rbegin() and rend(), they both return reverse iterators. Is there some type of implicit conversion that allows these reverse iterators to act as Forward Iterators?
At first, I suspected that the .base() part of these iterators may be at play
generate(v1.rbegin().base(), v1.rend().base(), Sequence(10)); //Line II
This compiles but throws an error at run time (Which makes complete sense).
I also tried
generate (v1.rend().base(), v1.rbegin().base(), Sequence(10)); // LINE III
Output : 3, 4, 5, 6,
This compiles and runs but isn't equivalent to my original output (Line I), so this isn't what is happening.
Any help or input would be greatly appreciated.
You know what, reverse-iterators can be forward-iterators too!
Specifically, the term reverse-iterator means that they go reverse to the "natural" direction.
The term forward-iterator names a concept, which guarantees among others that you can make a copy of an iterator, and copy and original can be independently used to iterate the sequence, and look at the elements, however often you want.
Take a good look at it, and you will see that while both are based on the concept iterator, and while they add different additional requirements, those are not contradictory.
Actually, whenever you have a reverse-iterator, they are normally automatically derived by decorating a bidirectional iterator (which is a forward-iterator), though that is not quite a requirement.

For loops vs standard library algorithms with a relatively old compiler

I know code is better when there are not any confusing for loops in it. And it is always good to reuse the standard library algorithms when possible. However, I find that the syntax of iterators and algorithms looks really confusing.
I want to give a real life example from my current project: I want to copy the contents of vector<vector<QString>> in into vector<QVariant> out. I can't see the difference between:
for (int i = 0; i < in[0].size(); i++ )
{
if(in[0][i].isNull() || in[0][i].isEmpty() )
out[i] = "NONE";
else
out[i] = in[0][i];
}
and that:
std::transform(in[0].begin(), in[0].end(), out.begin(), [](const QString& a)->QVariant{
if(a.isNull() || a.isEmpty() )
return "NONE";
else
return a;
});
Since we have visual studio 2012 I even have to type the return value of my lambda. After using ranges like:
in[0].map!( a => a.isNull() || a.isEmpty() ? "NONE" : a ).copy(out);
in D language I simply can't live with the std::transform code above. And I am not even sure whether it is better than a basic for loop. My question is: is code using std::transform above better than the for loop?
At least in my opinion, the main problem here is that transform is simply the wrong tool for the job.
What you're trying to do is exactly what std::replace_copy_if does, so (no big surprise) it does it a lot more neatly.
I don't have Qt installed on the machine at hand, so I took the liberty of replacing your QVariant and QString code to just a std::vector<std::string>, but I believe the same basic idea should apply with the Qt types as well.
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <string>
int main() {
std::vector<std::string> input { "one", "two", "", "three" };
std::vector<std::string> output;
// copy input to output, replacing the appropriate strings:
std::replace_copy_if(input.begin(), input.end(),
std::back_inserter(output),
[](std::string const &s) { return s.empty(); },
"NONE");
// and display output to show the results:
std::copy(output.begin(), output.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
For the moment, this just replaces empty strings with NONE, but adding the null check should be pretty trivial (with a type for which isNull is meaningful, of course).
With the data above, I get the result you'd probably expect:
one
two
NONE
three
I should probably add, however, that even this is clearly pretty verbose. It will be nice when we at least have ranges added to the standard library, so (for example) the input.begin(), input.end() can be replaced with just input. The result still probably won't be as terse as the D code you gave, but at least it reduces the verbosity somewhat (and the same applies to most other algorithms as well).
If you care about that, there are a couple of range libraries you might want to look at--Boost Range for one, and (much more interesting, in my opinion) Eric Neibler's range library.
Your code can be improved by using ? : (it might be sensible to create a static QVariant QVNone; that you could use).
std::transform(in[0].begin(), in[0].end(), out.begin(),
[](const QString& a) // for C++14: (auto& a)
{ return a.isNull() || a.isEmpty() ? QVariant("NONE") : a; }
);
Note: this page documents QVariant(const QString&), so the compiler should be able to work out a common type for the ? : values.
C++11 provides automatic determination of lambda return type when there's a single return statement - see syntax (3) here. C++14 already introduces the ability to accept the argument ala (auto& a). Ranges over container elements would help simplify such loops further; I think they're proposed for C++17; a relevant paper's available here.
There are also functional (non-Standard) libraries for C++ that may offer you a notation more like the one you document for D. Library recommendations are off-topic here, but Google should turn up some candidates without much effort.

Is there a CompareTo method in C++ similar to Java where you can use > < = operations on a data type

I know that in java there is a compareTo method that you can write in a class that will compare two variables and return a value -1, 1, or 0 signifing greater than, less than, and equal to operations. Is there a way to do this in C++?
Background:
Im creating a modified string class in which it takes a string and an arraylist. I want to be able to compare the string in a traditional fashion where if its lower in the alphabet it will be less than, than higher it would be greater than. Than i just want the array list to be linked to the files to store pages in which the word was indexed on in a text file. Anyways the specifics do not matter since i already have the class written. I just need to create compareTo method that would be able to be used in the main of my cpp file or by other data type like various trees for instance.
Ill write the code in java as i know how and maybe someone can help me with C++ Syntax (im required to write in c++ for this project unfortunatly, and i am new to C++)
I will shorten the code to give the rough outline of what im doing than write the compareTo method as i know how in java
class name ModifiedString
Has variables: word , arraylist pagelist
Methods:
getWord (returns the word associated with the class, i.e its string)
appendPageList (adds page numbers to the array list, this doesnt matter in this question)
Hers how i would do it in java
int compareTo(ModifiedString a){
if(this.getWord() > a.getWord())
return 1;
else if (this.word() < a.getWord())
return -1;
else return 0;
}
Then when < , > , or == is used on a ModifiedWord than the operations would be valid.
std::string already includes a working overload of operator<, so you can just compare strings directly. Java uses compareTo primarily because the built-in comparison operator produces results that aren't generally useful for strings. Being a lower-level language, Java doesn't support user-defined operator overloads, so it uses compareTo as a band-aid to cover for the inadequacy of the language.
From your description, however, you don't need to deal with any of that directly at all. At least as you've described the problem, you really want is something like:
std::map<std::string, std::vector<int> > page_map;
You'll then read words in from your text file, and insert the page number where each occurs into the page map:
page_map[current_word].push_back(current_page);
Note that I've used std::map above, on the expectation that you may want ordered results (e.g., be able to quickly find all words from age to ale in alphabetical order). If you don't care about ordering, you may want to use std::unordered_map instead.
Edit: here's a simple text cross-reference program that reads a text file (from standard input) and writes out a cross-reference by line number (i.e., each "word", and the numbers of the lines on which that word appeared).
#include <map>
#include <unordered_map>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include "infix_iterator.h"
typedef std::map<std::string, std::vector<unsigned> > index;
namespace std {
ostream &operator<<(ostream &os, index::value_type const &i) {
os << i.first << ":\t";
std::copy(i.second.begin(), i.second.end(),
infix_ostream_iterator<unsigned>(os, ", "));
return os;
}
}
void add_words(std::string const &line, size_t num, index &i) {
std::istringstream is(line);
std::string temp;
while (is >> temp)
i[temp].push_back(num);
}
int main() {
index i;
std::string line;
size_t line_number = 0;
while (std::getline(std::cin, line))
add_words(line, ++line_number, i);
std::copy(i.begin(), i.end(),
std::ostream_iterator<index::value_type>(std::cout, "\n"));
return 0;
}
If you look at the first typedef (of index), you can change it from map to unordered_map if you want to test a hash table vs. a red-black tree. Note that this interprets "word" pretty loosely -- basically any sequence of non-whitespace characters, so for example, it'll treat example, as a "word" (and it'll be separate from example).
Note that this uses the infix_iterator I've posted elsewhere.
There is no standard way in C++ to define an operator that does what the Java compareTo() function does. You can, however, implement
int compareTo(const ModifiedString&, const ModifiedString&);
Another option is to overload the <, <=, >, >=, == and != operators, e.g. by implementing
bool operator<(const ModifiedString&, const ModifiedString&);
In C++, you define bool operator< directly, no need to invent funny names, same for operator< and operator==. They're generally implemented as member functions taking one extra argument, the righthand side, but you could also define them as non-member functions taking two arguments.
Sun decided to not include operator overloading in Java, so them provided an in-class way (through member functions) to do that job: The equals() and compareTo() functions.
C++ has operator overloading, which allows you to specify the behaviour of the language operators within your own types.
To learn how to overload operators, I suggest you to read this thread: Operator overloading

Iterating Streams in Reverse

I would like to use std::find_if to traverse the contents of an std::streambuf in reverse. This involves constructing an std::reverse_iterator from an std::istream_iterator or std::istreambuf_iterator. Unfortunately, trying to do this, as shown in the code sample below, results in a compilation error. How can I get this to work? If necessary, solutions using Boost would be great.
#include <cstddef>
#include <fstream>
#include <iterator>
template <class Iterator>
static std::reverse_iterator<Iterator>
make_reverse_iterator(Iterator i)
{
return std::reverse_iterator<Iterator>(i);
}
int main()
{
std::ifstream is{"foo.txt", std::ios::binary};
std::istreambuf_iterator<char> i{is};
auto r = make_reverse_iterator(i);
// Error =(
*r;
return EXIT_SUCCESS;
}
Here is the compilation error reported by g++-4.8.1:
In file included from /opt/local/include/gcc48/c++/bits/stl_algobase.h:67:0,
from /opt/local/include/gcc48/c++/bits/char_traits.h:39,
from /opt/local/include/gcc48/c++/ios:40,
from /opt/local/include/gcc48/c++/istream:38,
from /opt/local/include/gcc48/c++/fstream:38,
from ri.cpp:9:
/opt/local/include/gcc48/c++/bits/stl_iterator.h: In instantiation of 'std::reverse_iterator<_Iterator>::reference std::reverse_iterator<_Iterator>::operator*() const [with _Iterator = std::istream_iterator<char>; std::reverse_iterator<_Iterator>::reference = const char&]':
ri.cpp:24:3: required from here
/opt/local/include/gcc48/c++/bits/stl_iterator.h:163:10: error: no match for 'operator--' (operand type is 'std::istream_iterator<char>')
return *--__tmp;
^
Thanks for your help!
As far as I know input iterators (such as those of ifstreams) are not capable of going backwards which is why the reverse iterator is not available. Which makes sense because if you think about it, the forward of the reverse_iterator (i.e. operator ++) is the backwards of the normal iterator (i.e. operator --) and so if the normal iterator doesn't provide operator --, then it stands to reason that the reverse_iterator should not exist.
As I recall there are 3 types of iterators: forward, bidirectional and random access. Forward can only go in one direction (guess which :P), bidirectional can go forward and backwards by 1 and random access can go forwards and backwards by whatever increment.
As you can see random access iterators offer all the operations of bidirectional iterators (and more) who themselves offer all the operations of forward iterators (and more). Which means random access iterators can be used where forward iterators are require but not the other way around.
As you may have guessed from this explanation make_reverse_iterator most likely requires either bidirectional or random access iterators and ifstream most likely offers only forward which is why the template instantiation fails.

boost::regex_search refuses to take my arguments

I'm struggling on this one and I'm to a point where I not making any headway and it's time to ask for help. My familiarity with the boost libraries is only slightly better than superficial. I'm trying to do a progressive scan through a rather large string. In fact, it's the entire contents of a file read into a std::string object (the file isn't going to be that large, it's the output from a command line program).
The output of this program, pnputil, is repetitive. I'm looking for certain patterns in an effort to find the "oemNNN.inf" file I want. Essentially, my algorithm is to find the first "oemNNN.inf", search for identifying characteristics for that file. If it's not the one I want, move on to the next.
In code, it's something like:
std::string filesContents;
std::string::size_type index(filesContents.find_first_of("oem"));
std::string::iterator start(filesContents.begin() + index);
boost::match_results<std::string::const_iterator> matches;
while(!found) {
if(boost::regex_search(start, filesContents.end(), matches, re))
{
// do important stuff with the matches
found = true; // found is used outside of loop too
break;
}
index = filesContents.find_first_of("oem", index + 1);
if(std::string::npos == index) break;
start = filesContents.being() + index;
}
I'm using this example from the boost library documentation for 1.47 (the version I'm using). Someone please explain to me how my usage differs from what this example has (aside from the fact that I'm not storing stuff into maps and such).
From what I can tell, I'm using the same type of iterators the example uses. Yet, when I compile the code, Microsoft's compiler tells me that: no instance of overloaded function boost::regex_search matches argument list. Yet, the intellisense shows this function with the arguments I'm using, although the iterators are named something BidiIterator. I don't know the significance of this, but given the example, I'm assuming that whatever the BidiIterator is, it takes a std::string::iterator for construction (perhaps a bad assumption, but seems to make sense given the example). The example does show a fifth argument, match_flags, but that argument is defaulted to the value: boost::match_default. Therefore, it should be unnecessary. However, just for kicks and grins, I've added that fifth argument and still it doesn't work. How am I misusing the arguments? Especially, when considering the example.
Below is a simple program which demonstrates the problem without the looping algorithm.
#include <iostream>
#include <string>
#include <boost/regex.hpp>
int main() {
std::string haystack("This is a string which contains stuff I want to find");
boost::regex needle("stuff");
boost::match_results<std::string::const_iterator> what;
if(boost::regex_search(haystack.begin(), haystack.end(), what, needle, boost::match_default)) {
std::cout << "Found some matches" << std::endl;
std::cout << what[0].first << std::endl;
}
return 0;
}
If you decide to compile, I am compiling and linking against 1.47 of the boost library. The project that I'm working with uses this version extensively and updating isn't for me to decide.
Thanks for any help. This is most frustrating.
Andy
In general iterator's types are different.
std::string haystack("This is a string which contains stuff I want to find");
returning values from begin() and end() will be std::string::iterator.
But your match type is
boost::match_results<std::string::const_iterator> what;
std::string::iterator and std::string::const_iterator are different types.
So there is few variants
declare string as const (i.e. const std::string haystack;)
declare iterators as const_iterators (i.e. std::string::const_iterator begin = haystack.begin(), end = haystack.end();) and pass them to regex_search.
use boost::match_results<std::string::iterator> what;
if you have C++11 you can use haystack.cbegin() and haystack.cend()
example of work