0

I have a templatized function that takes in pointers.

template <typename T>
void foo(const T* bar){}

How can I change foo to ensure that I am being passed an iterator/pointer? I assume there is a static_assert or an enable_if way of doing this, but I can't seem to find it.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Why don't you simply on implicit interfaces provided by templates mechanisms ? Just do your function body as if you were passed an iterator/pointer and it'll work for everything "looking like" so. – Telokis Jul 28 '15 at 11:50
  • @Ninetainedo If I intend on exposing this function in my interface I need to do some defensive programming. Ideally providing the used of the interface information that `foo` was implemented incorrectly. – Jonathan Mee Jul 28 '15 at 11:53
  • If you really want to do so, I know there is a `std::is_pointer` type_trait but I don't know about iterators. – Telokis Jul 28 '15 at 11:59

2 Answers2

1

You may use std::iterator_traits to check if it is an iterator (or pointer)

template <typename IT>
decltype(std::iterator_traits<IT>::iterator_category{}, void())
foo(IT bar);
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • This seems to be the correct solution: "If Iterator does not have the five member types difference_type, value_type, pointer, reference, and iterator_category, then this template has no member types (std::iterator_traits is SFINAE-friendly)" [[source](http://en.cppreference.com/w/cpp/iterator/iterator_traits)] – Jonathan Mee Jul 28 '15 at 12:16
0

To check for a pointer, you can use std::is_pointer. To check for an iterator, you can define your own is_iterator trait as described in this answer. If you combine these two, you get:

#include <type_traits>
#include <iterator>

template<typename T, typename = void>
struct is_iterator
{
   static constexpr bool value = false;
};

template<typename T>
struct is_iterator<T, typename std::enable_if<
    !std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type>
{
   static constexpr bool value = true;
};

template<class T>
void test(T t) {
  static_assert(std::is_pointer<T>::value || is_iterator<T>::value,
                "T must be pointer or iterator");
}
Community
  • 1
  • 1
Robin Krahl
  • 5,268
  • 19
  • 32