Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Is it any nice way to call STL algorithms on an integer range?
For example I have a collection "col" with access to it's elements only via GetElement(int) method. Is it possible to use find_if function to find something in that collection?
I would like to call something like that:
auto element =
find_if(0, col.Size(), [&col] (int i) {
return predicate(col.GetElement(i));
});
I'm looking for an STL or any other library solution.
With standard C++? Yes, if you write a custom element iterator. Then, your code is easily simplified to:
auto element = find_if(col.begin(), col.end(), predicate);
It's not possible to do something closer to what you had in mind with the standard library, but it is with Boost, which is an incredible C++ library that you really ought to have. Boost has a counting iterator: http://www.boost.org/doc/libs/1_55_0/libs/iterator/doc/counting_iterator.html
How would you fill up a vector with the numbers zero through one hundred using std::copy()? The only iterator operation missing from builtin integer types is an operator*() that returns the current value of the integer. The counting iterator adaptor adds this crucial piece of functionality to whatever type it wraps. One can use the counting iterator adaptor not only with integer types, but with any incrementable type.
#include <boost\counting_iterator.hpp> //or something, not sure of exact header
int main() {
boost::counting_iterator<int> first(0);
boost::counting_iterator<int> last(col.Size());
auto element = find_if(first, last, [&col](int i) {return predicate(col.GetElement(i);});
}
Additionally, boost also has ranges. They don't really help you much in this exact situation, but it's related, so I'll mention it:
#include <boost\range\irange.hpp>
int main() {
for (int index: boost::range::irange<int>(0, col.Size()) )
{
std::cout << element; //counts from 0 to col.Size()
}
}
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
for (auto& i : just_a_vec )
Or an iterator for loop.
for (std::vector<std::string>::iterator it = just_a_vec.begin(); it < just_a_vec.end(); it++)
Iterators predate range-based for loops, so they used to be the only of these two alternatives available. Nowadays, range-based for has mostly replaced iterators when dealing with a simple loop.
However, iterators can be used in various other contexts as well. For example, you can do std::sort(v.begin(), std::next(v.begin(), 5)) to sort the first five elements of a vector while leaving the rest of it alone.
Going back to iterating over a whole container:
If you can accomplish what you want with a range-based for, then it leads to more legible code, so they are preferable by default.
If you need iterators for some reason, such as using an algorithm that requires them, or because you need to jump ahead or back while iterating, then use those instead.
Also: In the later case, you can/should still use auto when declaring the iterator:
for(auto it = just_a_vec.begin(); it < just_a_vec.end(); it++) {
}
Edit: as asked: here's a simple, if a bit contrived, example where an iterator-based loop can still be useful:
// adds all values in the vector, but skips over twos values when encountering a 0
// e.g.: {1,2,0,4,5,2} => 5
int my_weird_accum(const std::vector<int>& data) {
int result = 0;
for(auto it = data.begin(); it != data.end(); ++it) {
auto v = *it;
result += v;
if(v == 0) {
// skip over the next two
assert(std::distance(it, data.end()) > 2);
std::advance(it, 2);
}
}
return 0;
}
Quick personal answer: Its somewhat sylistic and based on what version of c++ you are using. I typically prefer range based, but there are certainly moments iterators shine as well. Add both to your toolchest. For further reading.
Here is a list of other SO answers that get more into the performance and use cases.
What's the difference between iterator syntax in range-based loops for STL containers
Is the ranged based for loop beneficial to performance?
range based for loop vs regular iterator for loop
For further information. Google
Range vs iterator loop c++
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I know two forms to write loop functions with pointers in c++: using size of array or using the end of array.
Use the length:
float summationArray(float* numbers, int length){
if(length == 1){
return *numbers;
}
return *numbers + summationArray(numbers + 1, length - 1);
}
Use the end
float summationArray(float* numbers, float* end){
if(numbers == end){
return *numbers;
}
return *numbers + summationArray(numbers + 1, end);
}
What's is the better option?
Pre C++20, two iterators are better because they allow the function work on all types of iterators even those that don't know the size of the range. This is the convention most of the standard library follows.
Post C++20, you would probably use a range.
PS: Don't use recursion to calculate a sum. That's a bad idea. Use std::accumulate or at least a proper iterative loop.
I don't think one option is strictly better than the other, but the idiomatic approach in C++ is usually to use a pointer ("iterator") to the start and end of the container. Compare, e.g., with std::accumulate.
From a perspective on how they manage resources they are the same, so studying them from a time complexity point... they are the same too, the main difference on this to methods is how you obtain the size or the end pointer, but you only need to do it once, so the time it takes related to the size of the array will not change, cause is a single operation for the hole execution of the algorithm.
So calling them (when not having the size in a variable) looks like:
float value = summationArray(array, sizeof(array)/sizeof(array[0]));
float value = summationArray(array, std::end(array));
So I think, I would go with the end option, since it looks more """"pro""""", it's cleaner and is more c++ style.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating function, which takes a vector of operators( different matrices). Operators can be provided in different ordering ( from the smallest to biggest or other way around).
I need to create for loop based on ordering
for(auto tr = operators.begin(); tr != operators.end() ; ++tr )
or
for(auto tr = operators.end(); tr != operators.begin() ; --tr )
content inside of loop stays same
is there any way how to do this automatically? maybe based on some help input parameter?
You can support this by having your function consume a pair of iterators (a "range") instead of a complete matrix or vector. For example:
template <typename Iterator>
void print(Iterator begin, Iterator end) {
for(auto tr = begin; tr != end; ++tr)
; // ...
}
This way, you can pass any sort of range in: forward, reverse, or others. This is how much of the STL is designed.
If you use a std::vector for example, you'd invoke the above like so:
std::vector<int> vec;
print(vec.begin(), vec.end()); // forward
print(vec.rbegin(), vec.rend()); // reverse
Although, technically, an end() iterator can often be decremented and dereferenced safely, you are relying on specific properties that not all iterators are guaranteed to have.
A number of standard containers [some introduced in C++11 do not] have both forward iterators (which iterate through elements in order) and reverse iterators (which iterate over elements in the opposite order). The counterparts of begin() and end() are rbegin() and rend() respectively.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
all
I am using vector in C++ STL to store my data. I pass and return them into and from functions. However, as the data size grows, the program is slower and slower. Thus I am updating the codes to an "iterator version".
What I want to archieve is that use iterators to pass, return and iterate STL vectors.
I am now ok with the operations with 1-dimensional vector, just like manipulating the arrays. However, when it comes to 2-dimensional vector, I am a bit confused.
Can anyone show me a simple code example that how to iterate a 2D vector using STL iterator?
Many thanks in advance.
Regards
Long
You state that your basic problem is performance, right?
You assume that this is caused due to copying.
Perhaps there could be simpler solutions for your problem:
Check if vectors can be passed by (const) reference
Check if shared_ptr makes sense
Consider if move semantics can help
Perhaps compiler version or implementation prevent return value optimization
If you need to know the size of a vector, and have two iterators it1 it2,
std::distance(it1, it2);
will tell you the distance between them. This will happen to be the size if they are begin and end
If you have a function like
int work(std::vector<int> items)
{
//...
}
this copies the vector items, so will use more RAM and take longer.
Sending a const ref instead will not copy the vector. Making it const stops you changing it, which might not help you, but you haven't posted any code so I don't know what you want to do.
int work(const std::vector<int> & items)
{
//...
}
Well its already somewhere on stackoverflow
But if you don't want to search here it is :
std::vector<std::vector<int> > vec{ {1,2,3},{4,5,6}};
//Simplest Way:- (C++11)
for(auto row:vec)
{
for(auto col:row)
std::cout<<col<< " ";
std::cout<<std::endl;
}
//OR Using iterator
std::vector<std::vector<int> >::iterator r;
std::vector<int>::iterator c;
for (r = vec.begin(); r != vec.end(); r++) {
for (c = r->begin(); c != r->end(); c++) {
std::cout<<*c<< " ";
}
std::cout<<std::endl;
}
Can get distance only between two iterators of same container
std::vector<int>::iterator s = v2.begin(); //Can be any start
std::vector<int>::iterator e = v2.end(); // Can be any end
std::cout<<"Distance :"<<std::distance(s,e)<<std::endl;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Is it possible to use the tools only needing Iterators and a function-pointer from the module <algorithm> on PyObjects ?
The concrete problem I want to solve (it is constructed to learn from it):
I have a huge list of IDs stored in a python-list
Now I want to perform a std::binary_search on this list, using a module written in C++
One way could be to access the python-list as c-array, constructing a vector from it (which uses the pointers/ does not copy), doing the binary_search and export the array as PyObject.
Would that be possible?
Well, a binary search isn't that complicated, so why don't you simply code one based on a range of indices instead of iterators? I believe that a list conforms to the sequence protocol of Python, so that should be pretty easy.
If you really want to use the binary_search() algorithm for a learning experience, there is also the possibility to create STL-style iterators on top of the Python sequence. All you need is a pointer to the sequence and an index to create a random-access iterator. If you want to, you can also transparently convert the Python objects in the list into an according ID type (some integer type, I guess).
struct iterator
{
// typedefs required for fully compliant STL-style iterators
typedef PyObject* value_type;
iterator(PyObject* seqeunce, Py_ssize_t position):
m_sequence(sequence), m_position(position)
{
assert(PySequence_Check(m_sequence));
assert(m_position >= 0);
assert(m_position <= PySequence_GetSize(m_sequence));
}
value_type operator*() const
{
assert(m_position < PySequence_GetSize(m_sequence));
return PySequence_GetItem(m_sequence, m_position);
}
iterator& operator++()
{
assert(m_position <= PySequence_GetSize(m_sequence));
++m_position;
return *this;
}
iterator& operator+=(size_t l)
{
m_position += l;
return *this;
}
};
I haven't compiled this and probably forgot a few parts, but I guess you get the idea. Just init two iterators, one with an offset of zero and one with an offset of the size of the container and give those to binary_search().