I'm trying to write a generic function which will derive a return type at compile time according to the iterator it is given. Usually this is done through std::iterator_traits, but I also wanted to define my own version of iterator_traits, called my_iterator traits. Here's my code:
#include <cassert>
#include <iterator>
#include <vector>
using namespace std;
template <typename I>
struct my_iterator_traits {
typedef typename I::value_type value_type;
typedef typename I::iterator_category iterator_category;
};
template <typename T>
struct my_iterator_traits<T*> {
typedef T value_type;
typedef std::random_access_iterator_tag iterator_category;
};
template <typename II>
typename my_iterator_traits<II>::value_type f(II b, II e) {
typename my_iterator_traits<II>::value_type val = 0;
return val;
}
int main () {
int a[] = {2, 3, 4};
int i = f(a, a + 3);
assert(i == 0);
// vector<int> v = {2};
// f(v.begin(), v.end());
// assert(j == 0);
return 0;
}
Everything up to and including the main
function and the function f()
makes perfect sense. In main, I make an int
array, call f()
on it, and confirm that the output I get is an int whose value is zero.
What isn't clear is the following. I have two templates up top followed by the struct
keyword. It would make perfect sense to use the second one (the one that takes in T*
as the template argument). Specifically, why do we need the first struct template (the one without template parameters)? More importantly, what is the relationship between the two struct templates?