Я начал работать с boost: icl library, которая действительно всеобъемлющая и удобная. Я использую в основном два типа интервалов от boost, boost :: icl :: interval_set и boost :: icl :: interval_map. Иногда мне приходится манипулировать только интервальной частью обоих типов, и я не заинтересован в выполнении дублирующих функций.
Итак, вот мой пример:
template<typename T>
void UniqSegmentsInA(T &a,T &b,T &c,int max_gap=200)
{
typename T::iterator __it1 = a.begin();
typename T::iterator __it2 = b.begin();
bool _checking_=true;
while(__it1 != a.end() && __it2 != b.end())
{
typename T::interval_type __itv1 = getFirst(*__it1);
typename T::interval_type __itv2 = getFirst(*__it2);
if(__itv1.upper()>__itv2.upper())
{
/*if segments intersect and we should move second segment then segment A should not be included in output*/
if(intersects(T::interval_type::closed(__itv1.lower()-max_gap,__itv1.upper()+max_gap),__itv2)) _checking_=false;
__it2++;
}
else
{
if(!intersects(T::interval_type::closed(__itv1.lower()-max_gap,__itv1.upper()+max_gap),__itv2) && _checking_)
{
c.add((*__it1));
}
_checking_=true;
__it1++;
}
}
if(__it1 != a.end() && !_checking_) __it1++;
while(__it1 != a.end())
{
c.add(*__it1);
__it1++;
}
}
getFirst () является вспомогательной функцией, когда она является картой, а затем возвращает .first, когда это набор, а затем итератор.
bicl::interval_map<int,int>::interval_type inline getFirst(bicl::interval_map<int,int>::segment_type a)
{
return a.first;
}
bicl::interval_set<int>::interval_type inline getFirst(bicl::interval_set<int>::segment_type a)
{
return a;
}
Так что этот пример работает как ожидалось. То, что я хочу улучшить, это функция getFirst (), и я не хочу жестко кодировать типы доменов и кодоменов в interval_map / set. Я пробовал что-то вроде этого:
template<typename T>
typename bicl::interval_map<T,T>::interval_type inline getFirst(typename bicl::interval_map<T,T>::segment_type a)
{
return a.first;
}
Затем я изменил:
typename T::interval_type __itv1 = getFirst<typename T::domain_type>(*__it1);
typename T::interval_type __itv2 = getFirst<typename T::domain_type>(*__it2);
но это не работает и компилятор выдает ошибку:
src/Intersections.cpp:324:35: error: no matching function for call to ‘getFirst(const std::pair<const boost::icl::discrete_interval<int, std::less>, int>&)’
src/Intersections.cpp:324:35: note: candidates are:
src/Intersections.cpp:52:56: note: template<class T> typename boost::icl::interval_map<T, T>::interval_type getFirst(typename boost::icl::interval_map<T, T>::segment_type)
src/Intersections.cpp:57:56: note: boost::icl::interval_set<int>::interval_type getFirst(boost::icl::interval_set<int>::segment_type)
src/Intersections.cpp:57:56: note: no known conversion for argument 1 from ‘const std::pair<const boost::icl::discrete_interval<int, std::less>, int>’ to ‘boost::icl::interval_set<int>::segment_type {aka boost::icl::discrete_interval<int, std::less>}’
Итак, вопрос в том, возможно ли в этом примере не задавать жесткие коды типов доменов и кодоменов в функции getFirst ()?
Спасибо,
Андрей
Вы можете использовать шаблон функции
key_value
для этой цели. Определяется в
boost\icl\concept\set_value.hpp
and
boost\icl\concept\map_value.hpp
как это
template<class Type, class Iterator>
inline typename enable_if<is_set<Type>, const typename Type::key_type>::type&
key_value(Iterator it_)
{
return *it_;
}
template<class Type, class Iterator>
inline typename enable_if<is_map<Type>, const typename Type::key_type>::type&
key_value(Iterator it_)
{
return (*it_).first;
}
Других решений пока нет …