Утверждение аргумента шаблона является итератором/указателем

У меня есть шаблонная функция, которая принимает указатели.

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

Как я могу изменить foo, чтобы убедиться, что мне передается итератор/указатель? Я предполагаю, что есть static_assert или enable_if способ сделать это, но я не могу его найти.


person Jonathan Mee    schedule 28.07.2015    source источник
comment
Почему бы вам просто не использовать неявные интерфейсы, предоставляемые механизмами шаблонов? Просто сделайте свое тело функции, как если бы вам был передан итератор/указатель, и он будет работать для всего, что выглядит так.   -  person Telokis    schedule 28.07.2015
comment
@Ninetainedo Если я намерен использовать эту функцию в своем интерфейсе, мне нужно выполнить защитное программирование. В идеале предоставление информации об используемом интерфейсе, что foo был реализован неправильно.   -  person Jonathan Mee    schedule 28.07.2015
comment
Если вы действительно хотите это сделать, я знаю, что есть std::is_pointer type_trait, но я ничего не знаю об итераторах.   -  person Telokis    schedule 28.07.2015


Ответы (2)


Вы можете использовать std::iterator_traits, чтобы проверить, является ли он итератором (или указателем)

template <typename IT>
decltype(std::iterator_traits<IT>::iterator_category{}, void())
foo(IT bar);
person Jarod42    schedule 28.07.2015
comment
Кажется, это правильное решение: если у Iterator нет пяти типов членов: different_type, value_type, pointer, reference и iterator_category, то этот шаблон не имеет типов членов (std::iterator_traits совместим с SFINAE) [источник] - person Jonathan Mee; 28.07.2015

Чтобы проверить наличие указателя, вы можете использовать std::is_pointer. Чтобы проверить наличие итератора, вы можете определить свой собственный признак is_iterator, как описано в этом ответе. Если совместить эти два, вы получите:

#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");
}
person Robin Krahl    schedule 28.07.2015