Contiguous iterators (C++)?
-
@wharrgarbl said in Contiguous iterators (C++)?:
Duplicated code is easier to maintain than the C++ template clusterfuck.
No, it's not. Duplicated code is the worst maintenance nightmare; and good C++ developers know templates well enough to at least be able to maintain existing code.
And templates have another advantage: If you do something wrong, your compiler will complain loudly. It sure as hell won't complain about diverging versions of some duplicated logic, though.
-
@Kian said in Contiguous iterators (C++)?:
in the sense that Cthulhu is beautiful
Beautiful… maybe. Cute for sure though!
-
@dkf said in Contiguous iterators (C++)?:
@Kian said in Contiguous iterators (C++)?:
in the sense that Cthulhu is beautiful
Beautiful… maybe. Cute for sure though!
-
WTF? Actually useful content on this site???
A new book was just published which [IMPO] does a good job on capabilities in modern C++....
-
@asdf said in Contiguous iterators (C++)?:
and good C++ developers know templates well enough to at least be able to maintain existing code.
Any concept that depends on good humans doesn't work
-
@wharrgarbl said in Contiguous iterators (C++)?:
Any concept that depends on good humans doesn't work
Says the C programmer. How ironic.
-
@TheCPUWizard said in Contiguous iterators (C++)?:
WTF? Actually useful content on this site???
I figured that my chances of getting a useful answer around here were higher than on SO, where people would inevitably attempt to convince me that what I want to do really isn't what I want to do, and that I'm a bad person for thinking that I want to do that. Followed by two pages of copy-pasta from the standard (on a lucky day) or two pages of copy-pasta from some unrelated beginner's tutorial (on an average day). (Said answer would then be upvoted over my protests because I don't have enough internet pointz.)
(Also, I don't have a SO account. Hence the lack of internet pointz.)
Filed under: I'll take wharrgarbl's attempts at trollery over that any day.
-
@LB_ said in Contiguous iterators (C++)?:
Ah, it was a silly mistake. Working demo: https://ideone.com/UVKTHh
Expand for code:
template<typename Iterator, typename U = typename std::vector<typename std::iterator_traits<Iterator>::value_type>::iterator, typename = void> auto f(Iterator beg, Iterator end) -> typename std::enable_if<!std::is_same<Iterator, U>::value, void>::type { for(auto it = beg; it != end; it = std::next(it)) { std::cout << *it << " iterator!" << std::endl; } } template<typename Iterator, typename U = typename std::vector<typename std::iterator_traits<Iterator>::value_type>::iterator> auto f(Iterator beg, U end) -> typename std::enable_if<std::is_same<Iterator, U>::value, void>::type { for(auto it = beg; it != end; it = std::next(it)) { std::cout << *it << " vector!" << std::endl; } }
@asdf it's not fundamentally impossible, it's just really tricky.
This almost works. :-/. There's one somewhat annoying problem, and then a gotcha or two.
First,
std::array
's iterator on MSVC also depends on the size of the array (it's something likestd::_Array_iterator<type,size>
). So, the following:std::array<int,10> a; using Iter_ = decltype(a.begin()); static_assert( std::is_same< Iter_, typename std::array< typename std::iterator_traits<Iter_>::value_type, 11 >::iterator >::value )
fails the assertion. There's no standardized way of getting the size of the array from one of its iterators (AFAIK; the other standard libraries don't even have the information in their iterators, though), so one would again have to go dig around in the implementation details.
The gotcha is somewhat similar and related to custom allocators (less worried about those, though). The iterators' types again depend on the allocator on MSVC. libstdc++ has the same problem. libc++'s iterator doesn't depend on the allocator, so there's a chance that it would work. (As an aside, libc++ probably doesn't support allocators that use a custom fancy pointer type because of this.)
Here are my quick tests.
-
@asdf said in Contiguous iterators (C++)?:
Says the C programmer. How ironic.
C depends on evil humans.
-
@cvi You could recursively check higher and higher array sizes starting from 0 with a helper template. I'm not sure if exceeding the maximum recursion depth would act like SFINAE though.
-
@asdf said in Contiguous iterators (C++)?:
@wharrgarbl said in Contiguous iterators (C++)?:
Any concept that depends on good humans doesn't work
Says the C programmer. How ironic.
I don't use C where something saner would do the job.
-
@LB_ said in Contiguous iterators (C++)?:
@cvi You could recursively check higher and higher array sizes starting from 0 with a helper template. I'm not sure if exceeding the maximum recursion depth would act like SFINAE though.
Yeah.
You could just select a maximum size up-front. (Probably should, pretty sure that reaching maximum recursion depth used to be a hard error on GCC; it's been a while since I've seen that error, though, so it might have changed).
I don't usually worry too much about the compilation time (not dealing with that large software). But this seems like it could get to the point where it's a problem. After all, the worst case occurs when it's not a
std::array
iterator at all - you have to check all possible sizes to conclude that. Then again, at some sizesstd::array
stops making sense compared to astd::vector
. (Then again again, I hardly ever see anstd::array
or use it myself, so I might just ignore it altogether.)As mentioned in the OP, the other option is to just specialize for
_Array_iterator
and similar and be done with it. Not pretty, but gets the job done.Filed under: decisions
-
@cvi no, this is the way to do it https://stackoverflow.com/a/35988594/225186
Of course, it could be much better to have a static constexpr size member function.
-
@Alfredo-Correa the problem is that that information is not available from a
std::array<>::iterator
-
@Alfredo-Correa What @LB_ said.
If I had the access to the
std::array
type, figuring out the size would be trivial. The iterator (to which I do have access) is a typedef insidestd::array
, and it's not used as a base-class. So to figure out its size template parameter (when it has one), I don't need to do the polymorphic matching via a function + decltype, I could just match against it directly. That however involves knowing the actual template of the iterator (i.e.,_Array_iterator<>
for the MSVC implementation) -- but as stated in the original question, I'd like to avoid relying on undocumented internals of the standard library implementations if that's feasible.Filed under: the other SO problem -- provide an elaborate answer without understanding the question
-
@cvi ok, I get it. I had faced this problem before. It is almost imposible to retriver the container type from the iterator type.
BTW, in one of the implementations I use, std:::array<T, ...>::iterator is literally a raw pointer T*.
-
@Alfredo-Correa said in Contiguous iterators (C++)?:
BTW, in one of the implementations I use, std:::array<T, ...>::iterator is literally a raw pointer T*.
This is the case for both libstdc++ and libc++ (and for the former even if you enable its iterator debugging). It makes things easy, though -- the question is if an iterator is a contiguous iterator and therefore can be transformed into a raw pointer. If you have a raw pointer from the get-go, the answer to that question is trivially "yes". ;-)