This is a snippet of code that I’ve concocted to restricts the type that can be passed to a function to be only an iterator that enumerated values of a specified type. This allows for a more specialised templated function, where the parameters are guaranteed to be iterators over a certain other type.
template <class Iterator, class T>
struct enable_if_iterates_type :
public std::enable_if<std::is_same<typename std::iterator_traits<Iterator>::value_type, T>::value, T>
{
};
I hope I’ve made the code fairly self explanatory, but to summarise the Iterator template type is the iterator to accept, and T is the type that the iterator should enumerate. It is then used in the function to represent some type, usually the return type, as such:
template <class Iterator>
typename enable_if_iterates_type<Iterator, int>::type Generate(Iterator begin, Iterator end)
{
int i = 0;
std::generate(begin, end, [&i]() { return i++; });
return i;
}
Now this is just a simple example of how it can be used, where it limits the iterators that can be passed in to those that have a value_type of int. The full test program is at the end of the post.
This came about because in my game engine project I’ve created functions for computing a bounding box that contain a set of other bounding boxes. Initially I had it only accept a vector of bounding boxes, but using this snippet the function can now accept any pair of iterators that conform to the STL iterator mechanism and that iterate through a set of bounding boxes.
#include <iterator>
#include <algorithm>
#include <numeric>
#include <type_traits>
#include <vector>
#include <iostream>
template <class Iterator, class T>
struct enable_if_iterates_type : public std::enable_if<std::is_same<typename std::iterator_traits<Iterator>::value_type, T>::value, T>
{
};
template <class Iterator> typename enable_if_iterates_type<Iterator, int>::type Generate(Iterator begin, Iterator end)
{
int i = 0;
std::generate(begin, end, [&i]() { return i++; });
return i;
}
template <class Iterator> typename enable_if_iterates_type<Iterator, int>::type Sum(Iterator first, Iterator last)
{
return std::accumulate(first, last, 0);
}
int main()
{
std::vector<int> int_vector(20);
Generate(std::begin(int_vector), std::end(int_vector));
std::cout << "Vector: " << Sum(std::begin(int_vector), std::end(int_vector)) << std::endl;
std::copy(std::begin(int_vector), std::end(int_vector), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
return 0;
}