Varying argument values and number -- is this legal C++? - c++

I'm trying to declare the following two functions to put back together a tokenized string (broken up into a vector or other iterator-compatible data structure):
std::string ComposeTokens(std::vector<std::string> Tokens);
std::string ComposeTokens(std::iterator first, std::iterator last);
In the implementation file (not provided here -- it's fairly obvious), Visual Studio's IntelliSense isn't recognizing either implementation as valid, saying that both conflict with both declarations. Compiling produces a message that iterators must have a template.
Is there any way to do what I'm trying to, here? Would it work to declare iterator< string >, do I need pointers, etc.? And has the STL or Boost or some other library already done this?

std::iterator is a base class template which at least needs a category and a class type defined.
You don't generally define iterators this way - you define it using templates:
template <typename Iterator>
std::string ComposeTokens(Iterator first, Iterator last);
Also, you probably want to be passing your vector by reference:
std::string ComposeTokens(std::vector<std::string>& Tokens);

Just make your iterator function a template:
template <class Iterator>
std::string ComposeTokens(Iterator first, Iterator last);

You can use std::accumulate:
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
int main() {
std::vector<std::string> v{"put", "me", "together"};
std::cout << std::accumulate(v.begin(), v.end(), std::string()) << std::endl;
}

It's perfectly ok to overload methods. VS is not complaining about that.
I think it's complaining because you're not using iterators correctly.
When you ask a question about a compiler error it's best to post the actual error, you'll get better answers.
As for iterators, they are templated and std::iterator is incomplete, hence the error. If your iterators are supposed to come from a vector then use std::vector<std::string>::iterator instead.

std::iterator is not what you think it is.
The easiest solution would be:
template <typename Iter>
std::string ComposeTokens(Iter first, Iter last);

Related

Do you have to increment ostream_iterator when writing?

In many examples of ostream_iterator I notice that an increment operation is used between writes:
e.g.
#include <iostream>
#include <iterator>
using namespace std;
int main() {
ostream_iterator<char> itr{ cout };
*itr = 'H';
++itr; // commenting out this line appears to yield the same output
*itr = 'i';
}
On the cpp reference increment (operator++) is listed as a no-op. Is there a reason to include it despite being a no-op? Is it a "best-practice" to include?
Why does ostream_iterator exist at all, when you can print directly to cout?
Answer: to be used with functions that expect an iterator.
There is a bunch of requirements that a type has to satisfy to be "an iterator" (and that those functions expect), and overloading ++ and * in a certain way is one of them.
Both * and ++ do nothing for an ostream iterator. If you're asking if you should call them or not, you don't need ostream_iterator in the first place.
Consider a possible implementation of std::copy:
template<class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last,
OutputIt d_first)
{
for (; first != last; (void)++first, (void)++d_first) {
*d_first = *first;
}
return d_first;
}
This code works with all output iterators. It also works with std::ostream_iterator. ++d_first is a noop in this case, but it still it has to be valid code, because for other output iterators it is needed.
Actually the major reason for std::ostream_iterator to exists is to be used with such generic algorithms, otherwise you could just write to the stream directly. Its a nice example of iterators being the glue between algorithms and container or more generally the data. Algorithms can be generic and need not care where the data is actually coming from or going to, because the iterator implements the special case.
Also from cppreference on std::ostream_iterator::operator++:
Does nothing. These operator overloads are provided to satisfy the
requirements of LegacyOutputIterator. They make it possible for the
expressions *iter++=value and *++iter=value to be used to output
(insert) a value into the underlying stream.
For your actual question:
Is there a reason to include it despite being a no-op? Is it a "best-practice" to include?
No. There is no point in incrementing the iterator when you know its a std::ostream_iterator. The only reason it can be incremented (which is a noop) is for generic code.

How to use `boost::range` iterators with standard iterators

I have functions that take in std::vector iterators, as in
typedef std::vector<Point> Points;
Points ConvexHull(Points::const_iterator first, Points::const_iterator last);
I usually pass the std iterators to them, but occasionally I need to work with boost iterators, such as boost::join's range iterator. How should I change the parametrizations of my functions, ideally without templates, so that they accept both iterators? Moreover, how do I indicate in each type which iterator concepts I need?
I tried looking at the boost::range documentation but it's overwhelmingly confusing for me and I don't know where to start.
For example, I couldn't find the difference between boost::range_details::any_forward_iterator_interface and boost::range_details::any_forward_iterator_wrapper, and whether I should use either of those to specify that I need a forward iterator.
Edit:
If I use boost::any_range, how can I pass non-const lvalue references?
For example:
template<typename T>
using Range = boost::any_range<T, boost::random_access_traversal_tag,
T, std::ptrdiff_t>;
f(Range<Point> &points); // defined elsewhere
// -------------
vector<Point> vec;
f(vec); // error; cannot bind non-const lvalue reference to unrelated type
boost-range has the any_range for this purpose and it suits both purposes for your case.
https://www.boost.org/doc/libs/1_60_0/libs/range/doc/html/range/reference/ranges/any_range.html
From your example it would look like this:
#include <boost/range/any_range.hpp>
typedef boost::any_range<Point,
boost::bidirectional_traversal_tag,
Point,
std::ptrdiff_t
> PointRange;
You should strongly consider using a template. Doing so let's the compiler keep useful information about what operations are actually occurring, which greatly helps it generate optimised output. The std:: convention is to name the type parameter for the concept required. E.g.
template< class BidirIt, class UnaryPredicate > // anything bidirectional (which includes random access)
BidirIt std::partition( BidirIt first, BidirIt last, UnaryPredicate p );
If you really don't want a template, you still shouldn't name anything in a detail namespace. Something like
#include <boost/range/any_range.hpp>
using PointRange = boost::any_range<Point, boost::random_access_traversal_tag>; // or another traversal tag.
using PointIterator = PointRange::iterator;
You will likely need to pass PointRange & less frequently than, say, int *&. Almost always passing by value is the correct behaviour. It is cheap to copy, as it holds a begin and end iterator from the Range that it was constructed from, nothing more.

C++ generic iterator

I'm not sure if the answers I was able to find are the easiest way to do what I need. The simple template that I would know how to modify into a full solution to my problem would be code that accomplishes the following:
Takes as input two iterators pointing to the beginning and end of an iterable container (vector, list...) containing things of value type T.
Returns a std::vector<T> containing an element-by-element copy of the input container in whatever order accomplished by iterating the input container from beginning to end.
Something non-functioning would be like follows:
template<typename Iterator, typename T>
std::vector<T> dumb_copy(Iterator first, Iterator last) { ... }
Problem is that I would need the compiler to somehow check that I'm given iterators pointing to something of type T.
I'm currently learning C++ and writing as practice the most generic implementations of certain algorithms that I can think of, so I want to get the best practices right from the start. If there's an easy way of doing this using C++11 constructs, that's fine with me.
You can simply use traits to remove the T type completely, allowing it to be determined automatically:
template <typename Iterator>
std::vector<typename std::iterator_traits<Iterator>::value_type>
dumb_copy(Iterator first, Iterator last)
{
std::vector<typename std::iterator_traits<Iterator>::value_type> copy;
// Populate the copy vector
return copy;
}
In particular, note that std::iterator_traits has a specialization when the iterator type is a pointer, so this will allow your function to "just work" even when it is passed pointers instead of "true" iterator objects.
You don't need to do this because the standard library containers already work this way. So you can create a std::vector from two iterators directly:
#include <string>
#include <vector>
#include <iostream>
int main()
{
std::string s = "hello"; // iterable container
// construct a vector using two iterators
std::vector<std::string::value_type> v(s.begin(), s.end());
// check the results
for(unsigned i = 0; i < v.size(); ++i)
std::cout << v[i];
std::cout << '\n';
}
You can just create a std::vector<T> with a type matching the result of *it for one of the iterators:
#include <type_traits>
#include <vector>
template <typename Iterator>
auto dump_copy(Iterator begin, Iterator end)
-> std::vector<typename std::decay<decltype(*begin)>::type> {
return std::vector<typename std::decay<decltype(*begin)>::type(begin, end);
}
With C++14 you can replace typename std::decay<X>::type by std::decay_t<X>.

How to receive a iterator pair in a method?

How can I receive a iterator pair in my own function/method?
void moveMessages(const std::InputIterator<uint64_t> begin, const std::InputIterator<uint64_t> end, uint32_t to_folder_id, int32_t from_folder=-1);
Im trying like this, bug gcc dont like it.. Probably i am missing something important..
I found somewhere a template version to do this. It is possible to do this without templates? Probably its enogh to receive an "input iterator base class" as a parameter, but how to do this?
I found somewhere a template version to do this.
Yes, that's how to do it.
template <typename InputIterator>
void moveMessages(InputIterator begin, InputIterator end, uint32_t to_folder_id, int32_t from_folder=-1);
It is possible to do this without templates?
Not really. Different kinds of iterators are different, unrelated types, so you need a template to handle them polymorphically.
Probably its enogh to receive an "input iterator base class" as a parameter, but how to do this?
There is no base class. In fact, iterators are not necessarily class types at all: pointers can be used as iterators.

How to overload std::remove for std::list?

I once learnt that the general way to erase elements from a container is via the erase-remove-idiom. But I was surprised to find out that at least g++'s STL implementation does not overload std::remove() for std::list, since in this case a lot of object assignments could be saved by doing the reordering via pointer manipulation.
Is there a reason that the C++ standard does not mandate such an optimisation? But my main question is how I can overload std::remove() (it does not have to be portable beyond g++), so I could provide an implementation that use list::splice()/list::merge() instead. I tried a couple of signatures but get an ambiguity error at best, for example:
template <typename T>
typename std::list<T>::iterator
remove(typename std::list<T>::iterator first,
typename std::list<T>::iterator last, const T &v);
P.S.: I am sorry that I was not clear enough. Please ignore that the functions come from the std namespace and what they do specifically. I just wish to learn more about the template/typetraits/overload rules in C++.
It's not mandated because it's not just an optimization, it has different semantics from what you'd expect for a Sequence container:
std::list<int> l;
l.push_back(1);
l.push_back(2);
std::list<int>::iterator one = l.begin();
std::list<int>::iterator two = l.end(); --two;
if (something) {
l.erase(remove(l.begin(), l.end(), 1), l.end());
// one is still valid and *one == 2, two has been invalidated
} else {
l.remove(1);
// two is still valid and *two == 2, one has been invalidated
}
Regarding the actual question: ISWYM, I'm stuck for the moment how to write a pair of function templates so that one matches arbitrary iterators and the other matches list iterators, without ambiguity.
Do be aware that there isn't actually any guarantee in the standard that list<T>::iterator is a different type from some_other_container<T>::iterator. So although in practice you'd expect each container to have its own iterator, in principle the approach is flawed quite aside from the fact that you suggested putting the overload in std. You can't use iterators alone to make "structural" changes to their corresponding containers.
You can do this without ambiguity:
template <typename Container>
void erase_all(Container &, const typename Container::value_type &);
template <typename T>
void erase_all(std::list<T> &, const T &);
list::remove or list::erase alone will do what you've seen the erase/remove idiom do for vectors.
remove for values or predicates. erase for single iterators or ranges.
The advice you received is good, but not universal. It is good for std::vector, for instance, but completely innecessary for std::list since std::list::erase() and std::list::remove() already do the right thing. They do all the pointer magic you request, something std::vector::erase() cannot do because its internal storage is different. This is the reason why std::remove() is not specialised for std::list: because there is no need to use it in this case.