// std::vector<double>::iterator it {&v[0]};
// std::cout << *it << '\n'; // possible
I don't think you're supposed to be able to initialize a std::vector<double>::iterator with a pointer like that. It compiles with libstdc++ (GCC's implementation of the standard library) but not in debug mode (i.e. when using -D_GLIBCXX_DEBUG). It also doesn't seem to work with libc++ (Clang's own implementation) nor with MSVC.
A question about auto which has involved my mind for considerable time! :(
Would you use auto for functions parameters types if they're long and many ones (to shorten the function signature)?
Like void accum(auto bg, auto end); in the first post.
I assume it causes the signature to look shorter but also less readable making the code even error-prone potentially. As well as, auto as the parameter type should be used usually instead of a template not everywhere just to shorten the parameter types.
One remedy might be using using generally: using vecItr = std::vector<double>::iterator;
What are your thoughts and do you ever use auto for function parameters types just to make them shorter?
It probably doesn't make a lot of difference in this case because if you passed two different iterator types it would still fail to compile because std::accumulate doesn't accept iterators of different types but I still prefer the first one because it's nicer to get an error about the actual function I'm calling like:
error: no matching function for call to ‘accum(IterType1&, IterType2&)’
than to get an error about some implementation detail:
error: no matching function for call to 'accumulate(...
I agree with using explicit templates only if they're constrained, something which is harder when using auto.
If I consider not using templates in any form (explicit or auto), I will go for using aliases for such cases.
yeah, generally we shouldn't mess with using one of them instead of the other.
Of course things like ptr {&*iter} is possible.
The operator*() of the std::iterator gives you a reference to the "current" element. This then can be used to obtain a "raw" pointer to that element, by using the address-of (&) operator. So, yeah, you can get a "raw" pointer from an iterator.
But it is not possible the other way around. You can not simply wrap an arbitrary "raw" pointer into a specific type of iterator...
Note that a pointer to a vector or array element can be used as an iterator because it fulfills all requirements for being an iterator (a random-access iterator to be precise).
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
#include <vector>
#include <numeric>
int main()
{
std::vector<int> vec = {3, 2, 5};
int* begin = vec.data(); // same as &vec[0] if !vec.empty()
int* end = vec.data() + vec.size();
std::cout << std::accumulate(begin, end, 0); // prints 10
}
The above is perfectly valid and guaranteed to work.
I think an implementation is even allowed to define std::vector<T>::iterator as an alias for T* but none seems to do that. The situation for std::array and std::initializer_list is more interesting.
Why don't you, Peter, as a great coder, go for C++20/23. There're many things that can save your day when coding in them!
I guess you mean I should have used std::same_as?
I don't know everything. :)
Looking at same_as on cppreference (https://en.cppreference.com/w/cpp/concepts/same_as) it's not even clear to me that it can be used as a bool.
Concepts is a feature I still have a lot to learn about.
The compiler I have installed on my computer only have partial C++20 support.