Однообразность в STL
От: _nn_  
Дата: 25.08.04 12:17
Оценка:
Был вектор :
std::vector<int> x;
//...
std::sort(x.begin(),x.end(),x_compare);


Потом решил заменить на список(list), однако компилятор заругался на std::sort, благо в list есть своя функция sort.

Напрашивается вопрос почему не сделать функцию sort в векторе.
Или же почему не сделать функцию sort еще и так:
template<typename TContainer>
void sort(TContainer& c);


А потом перегружать для нужных контейнеров.
И тогда не будет проблемы выше.

Чем аргументираванно такое поведение ?

Спасибо.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Однообразность в STL
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 25.08.04 12:26
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Чем аргументираванно такое поведение ?


__>Спасибо.



Алгоритмы (sort, stable_sort) не могут использоваться со списками, потому что списки не поддерживают итераторы свободного доступа. Впрочем, для сортировкиэлементов в списках определена специальная функция sort()

Н. Джосьютис
"Что не завершено, не сделано вовсе" Гаусс
Re[2]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 12:31
Оценка:
Здравствуйте, sadomovalex, Вы писали:

S>Здравствуйте, _nn_, Вы писали:


__>>Чем аргументираванно такое поведение ?


__>>Спасибо.



S>

S>Алгоритмы (sort, stable_sort) не могут использоваться со списками, потому что списки не поддерживают итераторы свободного доступа. Впрочем, для сортировкиэлементов в списках определена специальная функция sort()

S>Н. Джосьютис

Я это же и написал.

Просто идея такая — вместо того чтобы пихать sort по классам, которые не могут работать с std::sort обычным.

Сделать еще одну функцию (написанно выше какую) и ее перегружать для всего где не работает std::sort обычный.

Почему не сделать так ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Однообразность в STL
От: denisku Россия  
Дата: 25.08.04 12:38
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Просто идея такая — вместо того чтобы пихать sort по классам, которые не могут работать с std::sort обычным.

__>Сделать еще одну функцию (написанно выше какую) и ее перегружать для всего где не работает std::sort обычный.
__>Почему не сделать так ?
Дык какая собсно тебе разница, вызывать функцию класса или передавать контейнер в глобальную функцию?
Извините за потраченный траффик..
Re: Однообразность в STL
От: Кодт Россия  
Дата: 25.08.04 12:40
Оценка:
Здравствуйте, _nn_, Вы писали:

<>

std::sort это — изначально — разновидность быстрой сортировки контейнеров с произвольным доступом (массивы, std::vector).
std::list::sort использует алгоритм сортировки двухсвязных списков.
std::set/map/multiset/multimap вообще сортировать нельзя.

Для контейнеров с медленным произвольным доступом (по forward iterator'у) можно написать разновидность быстрой сортировки. Но вроде бы ни в одной версии STL этого не сделали.

В принципе, можно сделать функцию-диспетчера, которая различала бы тип контейнера и выполняла ту или иную сортировку.
template<class V, class A, class P>
void sort_container(std::vector<V,A>& cont, P pred)
{
  std::sort(cont.begin(), cont.end(), pred);
}

template<class V, class A, class P>
void sort_container(std::list<V,A>& cont, P pred)
{
  cont.sort(pred);
}

template<class C>
void sort_container(C& cont)
{
  sort_container(cont, std::less<typename C::value_type>());
}
Перекуём баги на фичи!
Re[3]: Однообразность в STL
От: Аноним  
Дата: 25.08.04 12:43
Оценка:
Так ведь таким образом ты и потеряешь внешнюю, видимую пользователю однообразность, у тебя будет что-нить вроде

template<class Cont>
void Sort(Cont &);

template<class T>
void Sort(list<T> &);//допустим, вижуал 6.0 не сможет определить кто из функций лучше подходит, но это
//уже дело десятое

А что с ассоциативными контейнерами делать?
Re: Однообразность в STL
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 25.08.04 13:01
Оценка: +1
Здравствуйте, _nn_, Вы писали:

__>Напрашивается вопрос почему не сделать функцию sort в векторе.

__>Или же почему не сделать функцию sort еще и так:
__>
__>template<typename TContainer>
__>void sort(TContainer& c);
__>


Ага, согласен, там еще много интересных функций которые хотелось бы так же перегрузить, например for_each. Такие разновидности я уже реализовал здесь, например kafe/algorithm.hpp (CVS версия).

__>А потом перегружать для нужных контейнеров.

__>И тогда не будет проблемы выше.
Этого не делал, не было надобности.

__>Чем аргументираванно такое поведение ?


Историей наверно, да к тому же в STL много функций, которые должны работать именно с итераторами, а не с контейнерами, видимо решили базироваться на чем то одном (для общности ).

PS. Просматривая стандартный <algorithm> все время вспоминал про то, что как было бы здорово иметь нормальные ламбда функции в C++. Половину STL можно было бы выкинуть
getboost.codeplex.com
citylizard.codeplex.com
Re: Однообразность в STL
От: Aera Беларусь  
Дата: 25.08.04 13:03
Оценка: 2 (1) +1
Здравствуйте, _nn_, Вы писали:

__>
__>template<typename TContainer>
__>void sort(TContainer& c);
__>

Можно сортировать не только контейнеры целиком, но и часть контейнера, в т.ч. и когда контейнер не является классом:

int a[10];
std::sort(a, a+10);
--
RedApe
Re[2]: Однообразность в STL
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 25.08.04 13:16
Оценка:
Здравствуйте, Aera, Вы писали:

A>Можно сортировать не только контейнеры целиком, но и часть контейнера, в т.ч. и когда контейнер не является классом:


A>
A>int a[10];
A>std::sort(a, a+10);
A>


Это легко лечиться классом оболочкой, которая содержит в себе пару итераторов

Например, так:
/// Array reference.
template<class ValueType>
class array_ref: 
{
public:
    template<int Size>
    array_ref(ValueType (&X)[Size]): Begin(X), End(X+Size) {}

    // здесь интерфейсы контейнера, такие как typedef ... iterator, iterator begin() и т.д. ...
    ...
private:
    ValueType *Begin;
    ValueType *End;
};

/// Creates an array reference.
template<class ValueType, int Size>
array_ref<ValueType> make_array_ref(ValueType (&X)[Size]) 
{ 
    return array_ref<ValueType>(X); 
}


Тогда пример будет выглядеть так:
int a[10];
std_ex::sort(make_array_ref(a));


Заметь, безопаснее, так как размер массива может измениться в следующей версии программы. Пример реализации array_ref здесь.
getboost.codeplex.com
citylizard.codeplex.com
Re[3]: Однообразность в STL
От: LaptevVV Россия  
Дата: 25.08.04 13:26
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Просто идея такая — вместо того чтобы пихать sort по классам, которые не могут работать с std::sort обычным.


__>Сделать еще одну функцию (написанно выше какую) и ее перегружать для всего где не работает std::sort обычный.


Короче, надо паттерн "стратегия" в шаблонном варианте применить.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Однообразность в STL
От: LaptevVV Россия  
Дата: 25.08.04 13:28
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _nn_, Вы писали:


К><>


К>std::sort это — изначально — разновидность быстрой сортировки контейнеров с произвольным доступом (массивы, std::vector).

К>std::list::sort использует алгоритм сортировки двухсвязных списков.
К>std::set/map/multiset/multimap вообще сортировать нельзя.

К>Для контейнеров с медленным произвольным доступом (по forward iterator'у) можно написать разновидность быстрой сортировки. Но вроде бы ни в одной версии STL этого не сделали.


К>В принципе, можно сделать функцию-диспетчера, которая различала бы тип контейнера и выполняла ту или иную сортировку.

К>
К>template<class V, class A, class P>
К>void sort_container(std::vector<V,A>& cont, P pred)
К>{
К>  std::sort(cont.begin(), cont.end(), pred);
К>}

К>template<class V, class A, class P>
К>void sort_container(std::list<V,A>& cont, P pred)
К>{
К>  cont.sort(pred);
К>}

К>template<class C>
К>void sort_container(C& cont)
К>{
К>  sort_container(cont, std::less<typename C::value_type>());
К>}
К>

Можно и так, но ИМХО здесь "чисто конкретно" паттерн стратегия (policy) в шаблонном варианте надо применять.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 13:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _nn_, Вы писали:


К><>


К>std::sort это — изначально — разновидность быстрой сортировки контейнеров с произвольным доступом (массивы, std::vector).

К>std::list::sort использует алгоритм сортировки двухсвязных списков.
К>std::set/map/multiset/multimap вообще сортировать нельзя.

К>Для контейнеров с медленным произвольным доступом (по forward iterator'у) можно написать разновидность быстрой сортировки. Но вроде бы ни в одной версии STL этого не сделали.


К>В принципе, можно сделать функцию-диспетчера, которая различала бы тип контейнера и выполняла ту или иную сортировку.


А почему в STL это не предусмотрели ?
Тогда можно было бы использовать одну функцию для всего.

Можно будет писать такое :
template<typename TContainer>
class C
{
 TContainer c;
public:
 void sort()
 {
  std::sort_container(c);
 }
};
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Однообразность в STL
От: Aera Беларусь  
Дата: 25.08.04 14:01
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Aera, Вы писали:


_>Это легко лечиться классом оболочкой, которая содержит в себе пару итераторов


_>Например, так:

_>
_>/// Array reference.
_>template<class ValueType>
_>class array_ref: 
_>


_>Тогда пример будет выглядеть так:

_>
_>int a[10];
_>std_ex::sort(make_array_ref(a));
_>


_>Заметь, безопаснее, так как размер массива может измениться в следующей версии программы. Пример реализации array_ref


А какие вспомогательные классы нужны для следующего кода:

std::vector<int> vector(2000);

// заполняем

std::sort(vector.begin(), vector.end());
int prev_size=vector.size();

for(int index=0; index<200; ++index) 
  vector.push_back(some_value());

std::sort(vector.begin()+prev_size, vector.end()); // как быть сдесь

std::inplace_merge(vector.begin(), vector.begin()+prev_size, vector.end());
--
RedApe
Re[3]: Однообразность в STL
От: Кодт Россия  
Дата: 25.08.04 14:20
Оценка: +1
Здравствуйте, _nn_, Вы писали:

К>>В принципе, можно сделать функцию-диспетчера, которая различала бы тип контейнера и выполняла ту или иную сортировку.


__>А почему в STL это не предусмотрели ?

__>Тогда можно было бы использовать одну функцию для всего.

Потому что сортировка списка меняет порядок обхода, не меняя сами элементы. А сортировка массива — обменивает значения.

Криворукий эскиз быстрой сортировки над forward-итерируемым массивом. Заметьте, даже не над bidirectional.
template<class It, class Pred>
std::pair<It,size_t> dummy_partition(It begin, It end, Pred pred)
{
  if(begin == end) return std::make_pair(begin,0);

  It splitter = begin;
  It it = splitter; ++it;
  // invariant: [begin,splitter) < [splitter] < (splitter,it)
  size_t d = 0; // == distance(begin,splitter)

  while(it != end)
  {
    if(!pred(*splitter, *it)) // *splitter >= *it
    {
      swap(*splitter,*it);
      ++splitter; ++d;
    }
    ++it;
  }

  return std::make_pair(splitter,d);
}

template<class It, class Pred>
void dummy_sort_imp(It begin, It end, size_t size, Pred pred)
{
  while(size > 1)
  {
    // разбиваем интервал на два, с центральным элементом
    std::pair<It,size_t> part = dummy_partition(begin,end,pred);

    It end1 = part.first;
    It begin2 = end1; ++begin2;
    size_t size1 = part.second;
    size_t size2 = size-size1-1;

    // рекурсивно спускаемся в меньший из интервалов (оставляя больший для следующей итерации)
    if(size1*2 <= size)
    {
      dummy_sort(begin, end1, size1, pred);
      begin = begin2;
      size = size2;
    }
    else
    {
      dummy_sort(begin2, end, size2, pred);
      end = end1;
      size = size1;
    }
  }
}

template<class It, class Pred>
void dummy_sort(It begin, It end, Pred pred)
{
  // вычисляем размер интервала единожды (требуется O(N) инкрементов итератора)
  dummy_sort_imp(begin, end, std::distance(begin,end), pred);
}
Перекуём баги на фичи!
Re[4]: Однообразность в STL
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 25.08.04 14:21
Оценка:
Здравствуйте, Aera, Вы писали:

A>А какие вспомогательные классы нужны для следующего кода:


Можно так, используя sequence и make_sequence (см. там же, array_ref наследуеться от sequence):
std::vector<int> vector(2000);

// заполняем

std_ex::sort(vector);
int prev_size=vector.size();

for(int index=0; index<200; ++index) 
  vector.push_back(some_value());

std_ex::sort(make_sequence(vector.begin()+prev_size, vector.end())); // использовать оболочку sequence

std_ex::inplace_merge(vector, vector.begin()+prev_size); // здесь middle указываеться в конце.


Не утверждаю что всегда надо передавать контейнеры везде где не попадя (я уже говорил
Автор: sergey_shandar
Дата: 25.08.04
что есть случаи когда нельзя их использовать) и STL не собираюсь менять, но моему личному опыту, просто надоедает писать X.begin(), X.end() (а в основном именно такая последовательность встречаеться в коде), поэтому предлагаю пользоваться готовыми оболочками.
getboost.codeplex.com
citylizard.codeplex.com
Re[5]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 14:26
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Aera, Вы писали:


A>>А какие вспомогательные классы нужны для следующего кода:


_>Можно так, используя sequence и make_sequence (см. там же, array_ref наследуеться от sequence):

_>
_>std::vector<int> vector(2000);

_>// заполняем

_>std_ex::sort(vector);
_>int prev_size=vector.size();

_>for(int index=0; index<200; ++index) 
_>  vector.push_back(some_value());

_>std_ex::sort(make_sequence(vector.begin()+prev_size, vector.end())); // использовать оболочку sequence

_>std_ex::inplace_merge(vector, vector.begin()+prev_size); // здесь middle указываеться в конце.
_>


_>Не утверждаю что всегда надо передавать контейнеры везде где не попадя (я уже говорил
Автор: sergey_shandar
Дата: 25.08.04
что есть случаи когда нельзя их использовать) и STL не собираюсь менять, но моему личному опыту, просто надоедает писать X.begin(), X.end() (а в основном именно такая последовательность встречаеться в коде), поэтому предлагаю пользоваться готовыми оболочками.


Можно сделать проще, если это идет имено в таком порядке и рядом :
#define begin_end(c) c.begin(), c.end()

std::vector<int> x;
std::sort(begin_end(x));
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: Однообразность в STL
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 25.08.04 14:30
Оценка:
Здравствуйте, _nn_, Вы писали:

_>>Не утверждаю что всегда надо передавать контейнеры везде где не попадя (я уже говорил
Автор: sergey_shandar
Дата: 25.08.04
что есть случаи когда нельзя их использовать) и STL не собираюсь менять, но моему личному опыту, просто надоедает писать X.begin(), X.end() (а в основном именно такая последовательность встречаеться в коде), поэтому предлагаю пользоваться готовыми оболочками.


__>Можно сделать проще, если это идет имено в таком порядке и рядом :

__>
__>#define begin_end(c) c.begin(), c.end()

__>std::vector<int> x;
__>std::sort(begin_end(x));
__>


Согласен, но у меня просто аллергия на дефайны .
getboost.codeplex.com
citylizard.codeplex.com
Re[4]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 14:31
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _nn_, Вы писали:


К>>>В принципе, можно сделать функцию-диспетчера, которая различала бы тип контейнера и выполняла ту или иную сортировку.


__>>А почему в STL это не предусмотрели ?

__>>Тогда можно было бы использовать одну функцию для всего.

К>Потому что сортировка списка меняет порядок обхода, не меняя сами элементы. А сортировка массива — обменивает значения.


К>Криворукий эскиз быстрой сортировки над forward-итерируемым массивом. Заметьте, даже не над bidirectional.

Это не аргумент против добавления такой удобной вещи
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 14:34
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, _nn_, Вы писали:


_>>>Не утверждаю что всегда надо передавать контейнеры везде где не попадя (я уже говорил
Автор: sergey_shandar
Дата: 25.08.04
что есть случаи когда нельзя их использовать) и STL не собираюсь менять, но моему личному опыту, просто надоедает писать X.begin(), X.end() (а в основном именно такая последовательность встречаеться в коде), поэтому предлагаю пользоваться готовыми оболочками.


__>>Можно сделать проще, если это идет имено в таком порядке и рядом :

__>>
__>>#define begin_end(c) c.begin(), c.end()

__>>std::vector<int> x;
__>>std::sort(begin_end(x));
__>>


_>Согласен, но у меня просто аллергия на дефайны .

Почему ?

Мне кажется что в данном случае гараздо проще использовать макрос чем определять десяток функций, к которым может еще что-нибудь добавиться, вдобавок этот макрос можно пихать везде, а не к только определенным функциям.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Однообразность в STL
От: _nn_  
Дата: 25.08.04 14:35
Оценка:
Здравствуйте, denisku, Вы писали:

D>Здравствуйте, _nn_, Вы писали:


__>>Просто идея такая — вместо того чтобы пихать sort по классам, которые не могут работать с std::sort обычным.

__>>Сделать еще одну функцию (написанно выше какую) и ее перегружать для всего где не работает std::sort обычный.
__>>Почему не сделать так ?
D>Дык какая собсно тебе разница, вызывать функцию класса или передавать контейнер в глобальную функцию?
Разница в том что я смогу делать так : http://rsdn.ru/Forum/Message.aspx?mid=779712&amp;only=1
Автор: _nn_
Дата: 25.08.04
.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.