Jan Hudec
Jan Hudec

Reputation: 76346

std::iterator_traits for integral types in Microsoft standard library

I have a template function, that needs to be specialized for iterators. So what I did was along the lines of:

template <typename T>
void function2(T whatever, typename std::iterator_traits<T>::pointer) // ... iterator

template <typename T>
void function2(T whatever, ...) // ... non-iterator

template <typename T>
void function(T whatever) {
    function2(whatever, NULL);
}

And I've hit a wall, because Microsoft standard library specializes std::iterator_traits for all numeric types (bool, char, int, float…). And it does it so that reference and pointer are non-void, despite the fact that neither operator* nor operator-> can be called on those types.

Ok, I can checki the std::iterator_traits<T>::category derives std::input_iterator (actually I think std::forward_iterator is more appropriate in my case) at the cost of some more complex template machinery.

I would however be interested in knowing:

Upvotes: 1

Views: 122

Answers (1)

user743382
user743382

Reputation:

Other functions [res.on.functions]

[...]

2 In particular, the effects are undefined in the following cases:

  • for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause

In order to use iterator_traits<T>, T must be an iterator. If it isn't, the behaviour is undefined. You cannot detect whether a type T is an iterator at compile time. It is not even theoretically possible, since a type is allowed to support the same operators and typedefs as iterators, so that an implementation's generic iterator_traits<T> can be instantiated without any error or warning message, but with a completely different meaning.

Thinking about it, since your comment clarifies that a reasonable guess is good enough, I think you're best off using SFINAE and enable_if to detect core operations (unary * and prefix ++), using std::iterator_traits<T>::pointer only if those conditions are met.

Upvotes: 2

Related Questions