Задать вопрос

Использование decltype или…?

Читал я на выходных о STL и нахлынуло несколько мыслей.


Допустим, вы пишите класс для сортировки с единой одноименной функцией. Допустим также, что хотите сделать что-то схожее с STL. Смотрим на описание sort в STL.

template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);



1. Как заведено, по умолчанию объекты сравниваются оператором <.

2. Но к тому же, вы хотите, чтобы функция не просто сортировала по-умолчанию, но еще и принимала функциональный объект для сравнения (будь то указатель на функцию, функтор или лямбда-выражение).


Но хочется сделать так, чтобы сама функция сортировки была одна. Т.е. не разные реализации с сортировкой по умолчанию и кастомным компаратором с дублированием кода. Одна единая функция для сортировки.


На ум приходит сделать так. По сути, код сортировки находится только в той функции, которая с компаратором. А та, что без компаратора вызывает функцию с компаратором со стандартным функтором less.


Но взглянем на описание less:
template &lt;class T&gt; struct less {
  bool operator() (const T& x, const T& y) const {return x&lt;y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef bool result_type;
};



Это структура, для инициализации объекта которого нужно знать тип.

Т.е. нужно написать:
std::less&lt;тип&gt; comp;

И вызвать:
sort (first, last, comp);

Но в этом месте тип мы не знаем.


Можно воспользоваться новым стандартом С++11 и вызвать:
sort( first, last, std::less&lt; decltype(*first) &gt;() );


Но на сколько это правильно (мало того, что разыменовывается непонятно какой указатель, так еще и как быть со старыми компиляторами)? Как записать лучше (компактнее, красивее) по-другому? Просто интереса ради.

Вполне рабочая сортировка пузырьком вышеописанным способом, чтобы иметь лучшее представление
#include &lt;algorithm&gt;    // std::swap

class BubbleSort
{
public:

	template&lt; class RandomAccessIterator &gt;
	static void sort( RandomAccessIterator first, RandomAccessIterator last )
	{
		sort( first, last, std::less&lt; decltype(*first) &gt;() );
	}

	template&lt; class RandomAccessIterator, class Compare &gt;
	static void sort( RandomAccessIterator first, RandomAccessIterator last, Compare comp )
	{
		for( auto i = first; i != last; i++ )
		{
			for( auto j = i + 1; j != last; j++ )
			{
				if( comp( *j, *i ) )
					std::swap( *i, *j );
			}
		}
	}

private:
	BubbleSort(void);
	~BubbleSort(void);
};

  • Вопрос задан
  • 3782 просмотра
Подписаться 4 Оценить Комментировать
Решения вопроса 1
@vScherba
template< class RandomAccessIterator >
void sort( RandomAccessIterator first, RandomAccessIterator last )
{
    sort( first, last, std::less< std::iterator_traits<RandomAccessIterator>::value_type >() );
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы