[type_traits] Interest in is_iterator type trait?

Back in 2011, Howard Hinnant and I put together an is_iterator type trait based on code Howard had developed and used over a period of time. See http://beman.github.io/is_iterator/is_iterator.hpp for the actual code See http://beman.github.io/is_iterator/is_iterator_test.cpp for a test program. The intent was always to submit is_iterator to Boost, but we never got around to it. Now I need it in Boost.Filesystem, so I'd rather see it go in type traits than just sticking it into boost/filesystem/detail. If there is interest, and John Maddock gives the OK, I'll write docs and integrate into type_traits, then submit a pull request. --Beman

Here's something that I have been using on C++03 compilers to check if its an
iterator. It is somewhat similar, except it checks additionally for
`reference` and `pointer`.
template<class T1 = void, class T2 = void, class T3 = void, class T4 =
void, class T5 = void>
struct holder
{
typedef void type;
};
template
If there is interest, and John Maddock gives the OK, I'll write docs and integrate into type_traits, then submit a pull request.
I definately think it is something very useful to have. Perhaps, it should go in Boost.Iterator instead? -- View this message in context: http://boost.2283326.n4.nabble.com/type-traits-Interest-in-is-iterator-type-... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Aug 19, 2014, at 11:55 AM, Peter Dimov
Fwiw, I used something closely related in libc++ for SFINAE on the “member template members” of the containers (the ones taking iterators) to disambiguate them from the members/constructors not taking iterators, but having the same number of parameters. But instead of is_iterator, I needed is_input_iterator, is_forward_iterator, etc. These refinements are implemented similar to what Beman shows, but takes into account which std iterator tag the nested iterator_category type is implicitly convertible to. They can also be used instead of tag dispatching for the selection of an optimal algorithm. Howard

I actually have used a `has_iterator_traversal` trait to check iterator
traversal, like this:
template

On 19/08/14 19:09, pfultz2 wrote:
Why not just write template<class Iterator> void my_function_impl(Iterator it, std::input_iterator_tag) { ... } template<class Iterator> void my_function(Iterator it) { return my_function_impl(it, typename std::iterator_traits<Iterator>::iterator_category()); } It's simpler and it probably compiles faster too.

Howard Hinnant wrote:
That was exactly what I had in mind. Instead of enable_if on is_iterator<T>,
it's almost always better to use enable_if on is_convertible

On Aug 19, 2014, at 12:49 PM, John Maddock
Additionally in this example (a constructor), tag dispatching doesn’t truly work. One has to remove this constructor from the overload resolution set when I is not an iterator (or the right *kind* of iterator), else is_constructible

On Tue, Aug 19, 2014 at 11:55 AM, Peter Dimov
Like Howard, for SFINAE. The specific case is implementing the Filesystem TS, which in class path has this: template <class Source> path(const Source& source); Source can be a iterator to a NTCTS or a container. The value_type may be one of 5 char types, and may be the same or different from the value_type of the path. There are six path members templated on Source. I can reduce all that complexity to this implementation for the ctor, and then reused detail::append() to implement the five other member functions. { detail::append(source, m_pathname); } detail::append() has four overloads. enable_if using is_iterator<> distinguishes which overload should be selected. --Beman

On 19/08/14 19:00, Beman Dawes wrote:
Why do you want to implement this with SFINAE? SFINAE for many cases scales badly both in terms of code management and scalability. You're better off using overloading or class template (partial) specialization inside the implementation of the library.

On Wed, Aug 20, 2014 at 8:27 AM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
Good question. The actual constructor needs SFINAE to avoid over-aggressive use as an automatic conversion, so it was on my mind, but there is no reason the implementation needs to use SFINAE.
SFINAE for many cases scales badly both in terms of code management and scalability.
Agreed.
You're better off using overloading or class template (partial) specialization inside the implementation of the library.
That occurred to me yesterday, and I'm in process of doing the implementation with tag dispatched overloads. The code looks much cleaner. But as far as this discussion is concerned, is_iterator (or maybe is_input_iterator) is needed to drive the tag selection, so the question remains whether to add it to type_traits or to filesystem/detail. IFAICS there is enough motivation and interest to make it worth adding to boost.type_traits, but John as maintainer has the final say on that. --Beman

Mathias Gaunard wrote:
AFAIK an iterator T doesn't have to provide an iterator_category typedef, only std::iterator_traits<T> does.
That's true. However, pre-C++14, iterator_traits<It>::iterator_category
causes a hard error (not SFINAE) when It is not an iterator. In C++14, the
default iterator_traits<It> is empty when It doesn't have the nested types.
So
is_iterator

On 20/08/2014 15:52, Peter Dimov wrote:
Users that want boost::is_iterator to work on such iterators will need to specialize boost::iterator_traits in addition to std::iterator_traits. Boost could also pre-emptively specialize iterator_traits for well-known iterators that need this.
participants (6)
-
Beman Dawes
-
Howard Hinnant
-
John Maddock
-
Mathias Gaunard
-
Peter Dimov
-
pfultz2