2016-04-12 3 views
1

Как создать итератор, который ограничивает базовый тип? Например, я хочу создать функции, такие как следующие:Итератор C++ для определенного типа

void functionThatOperatesOnPointSequence(PointIterator begin, PointIterator end); 

Где последовательность Point объектов могут быть сохранены по-разному. Мой вариант использования имел бы дополнительную сложность: Point был бы шаблоном. то есть Point<int> или Point<double> будет в равной степени действительным.

Решения, использующие C++ 11/14 или Boost, являются допустимыми и предпочтительными.

+1

Вы что-то создали? Это переполнение стека, поэтому вы должны задать вопрос, указав, что вы приложили некоторые усилия. Не запрашивайте готовое решение. – sebap123

+0

'PointIterator :: operator *' может возвращать только один тип объектов. «PointIterator» должен быть аргументом шаблона. – user2079303

+1

'is_a_point > :: value'? – Jarod42

ответ

0

Вот немного метапрограммирования шаблонов. is_template_instance принимает шаблон, который принимает только типы и тип, и возвращает true, если этот второй тип является экземпляром первого шаблона.

template<template<class...>class Z, class T> 
struct is_template_instance:std::false_type{}; 
template<template<class...>class Z, class...Ts> 
struct is_template_instance<Z,Z<Ts...>>:std::true_type{}; 

Теперь мы хотим запросить тип значения итератора. Мы можем использовать std::iterator_traits непосредственно, или использовать псевдоним, как это:

template<class It> 
using it_value_type = typename std::iterator_traits<It>::value_type; 

Составим два выше, чтобы написать is_point_iterator шаблон:

template<class It> 
using is_point_iterator = is_template_instance< Point, it_value_type<It> >; 

Обратите внимание, что если вы передаете это не-итераторы, оно может не сработает в дружеской манере или может вернуть неверный результат (std::iterator_traits не гарантирует разумные значения возврата для неитераторов).

Но это, как правило, попадает в тела шаблонов.

template<class PointIterator, 
    class=std::enable_if_t< is_point_iterator<PointIterator>::value > 
> 
void functionThatOperatesOnPointSequence(PointIterator begin, PointIterator end) { 
    // ... 
} 

существует только ограниченная полезность.

Вы можете извлечь тип значения из PointIterator в более SFINAE дружественной манере, например:

template<class It> 
using it_value_type = std::decay_t<decltype(*std::declval<It>())>; 

, если вам нужна поддержка SFINAE.

+0

Вопрос также в том, что производный класс из «Точка ' следует рассматривать как «Точка» или нет. (Не в вашем случае в настоящее время). – Jarod42

+0

@ Jarod42 Я могу придумать легкое решение (основанное на перегрузке функции), которое не различает тип, полученный от «Point », и что-то с «оператором Point &()'. Возможно, я должен реорганизовать 'is_iterator_over ', чтобы упростить работу. – Yakk

Смежные вопросы