On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 25.06.13 01:33. Заголовок: Предложение по включению в стандарт C++ новых обобщенных функций std::reverse и std::sort


В подавляющем большинстве случаев стандартные алгоритмы std::reverse и std::sort (и аналогичные им функции члены классов std::forward_list и std::list) вызываются для всего контейнера. Поэтому было бы целесообразно включить в стандарт C++ соответствующие обобщенные функции std::reverse и std::sort, которые в качестве параметра имели бы ссылку на контейнер. Это упростило бы работу программиста по рутинному написанию вызовов соответствующих функций с указанием итераторов начала списка элементов контейнера и его конца.

Ниже приведен демонстрационный пример, иллюстрирующий идею предложения.
 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>
#include <vector>
#include <forward_list>
#include <list>


namespace N1 // std
{

template <typename T>
void reverse( T &c )
{
std::reverse( std::begin( c ), std::end( c ) );
}

template <typename T, typename Allocator>
void reverse( std::forward_list<T, Allocator> &f )
{
f.reverse();
}

template <typename T, typename Allocator>
void reverse( std::list<T, Allocator> &l )
{
l.reverse();
}

template <typename T>
void sort( T &c )
{
std::sort( std::begin( c ), std::end( c ) );
}

template <typename T, typename Allocator>
void sort( std::forward_list<T, Allocator> &f )
{
f.sort();
}

template <typename T, typename Allocator>
void sort( std::list<T, Allocator> &l )
{
l.sort();
}

template <typename T, typename Compare>
void sort( T &c, Compare comp )
{
std::sort( std::begin( c ), std::end( c ), comp );
}

template <typename T, typename Allocator, typename Compare>
void sort( std::forward_list<T, Allocator> &f, Compare comp )
{
f.sort( comp );
}

template <typename T, typename Allocator, typename Compare>
void sort( std::list<T, Allocator> &l, Compare comp )
{
l.sort( comp );
}

} // end of N1


int main()
{
int a[3] = { 1, 2, 3 };
std::forward_list<int> f( std::begin( a ), std::end( a ) );
std::list<int> l( std::begin( a ), std::end( a ) );
std::vector<int> v( std::begin( a ), std::end( a ) );

std::cout << "a:\t";
for ( int x : a ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "f:\t";
for ( int x : f ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "l:\t";
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "v:\t";
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << std::endl;

N1::reverse( a );
N1::reverse( f );
N1::reverse( l );
N1::reverse( v );

std::cout << "a:\t";
for ( int x : a ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "f:\t";
for ( int x : f ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "l:\t";
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "v:\t";
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << std::endl;

N1::sort( a );
N1::sort( f );
N1::sort( l );
N1::sort( v );

std::cout << "a:\t";
for ( int x : a ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "f:\t";
for ( int x : f ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "l:\t";
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "v:\t";
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << std::endl;

N1::sort( a, std::greater<int>() );
N1::sort( f, std::greater<int>() );
N1::sort( l, std::greater<int>() );
N1::sort( v, std::greater<int>() );

std::cout << "a:\t";
for ( int x : a ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "f:\t";
for ( int x : f ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "l:\t";
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << "v:\t";
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << std::endl;
}


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 3 [только новые]





ссылка на сообщение  Отправлено: 05.10.18 18:00. Заголовок: Похоже с включением ..


Похоже с включением в стандарт C++ выражений требований (requires expressions) будет не сложно написать обобщенные функции std::sort и std::reverse. Я еще не достаточно изучил это нововведение, но тем не менее представленный ниже код выполняет поставленную задачу. Естественно выражения требований у функций могут быть еще уточнены.

 
#include <iostream>
#include <forward_list>
#include <vector>
#include <iterator>
#include <algorithm>

template <typename Container>
void sort( Container &container ) requires requires() { &Container::sort; }
{
std::cout << "sort with requires is called.\n";
container.sort();
}

template <typename Container>
void sort( Container &container )
{
std::cout << "sort without requires is called.\n";
std::sort( std::begin( container ), std::end( container ) );
}

template <typename Container>
void reverse( Container &container ) requires requires() { &Container::reverse; }
{
std::cout << "reverse with requires is called.\n";
container.reverse();
}

template <typename Container>
void reverse( Container &container )
{
std::cout << "reverse without requires is called.\n";
std::reverse( std::begin( container ), std::end( container ) );
}

int main()
{
std::forward_list<int> lst = { 3, 2, 1 };

for ( const auto &item : lst ) std::cout << item << ' ';
std::cout << '\n';

sort( lst );

for ( const auto &item : lst ) std::cout << item << ' ';
std::cout << '\n';

reverse( lst );

for ( const auto &item : lst ) std::cout << item << ' ';
std::cout << '\n';

std::cout << '\n';

std::vector<int> v = { 3, 2, 1 };

for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';

sort( v );

for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';

reverse( v );

for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';

std::cout << '\n';

int a[] = { 3, 2, 1 };

for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';

sort( a );

for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';

reverse( a );

for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';

}

Вывод программы на консоль
 
3 2 1
sort with requires is called.
1 2 3
reverse with requires is called.
3 2 1

3 2 1
sort without requires is called.
1 2 3
reverse without requires is called.
3 2 1

3 2 1
sort without requires is called.
1 2 3
reverse without requires is called.
3 2 1


Опробовать программу можно с помощью онлайн компилятора по адресу http://melpon.org/wandbox
Нужно будет указать опцию компилятора -fconcepts

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 08.10.18 11:53. Заголовок: Возможно, также имее..


Возможно, также имеет смысл объявить обобщенные функции std::find, std::lower_bound, std::upper_bound и std::equal_range.

Ниже представлена демонстрационная программа, показывающая использование обобщенной функции lower_bound.

 
#include <iostream>
#include <functional>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>

template <typename Container, typename Key>
auto lower_bound( const Container &container, const Key &key ) requires requires() { &Container::lower_bound; }
{
std::cout << "lower_bound for a const object with requires is called.\n";
return container.lower_bound( key );
}

template <typename Container, typename Key>
auto lower_bound( Container &container, const Key &key ) requires requires() { &Container::lower_bound; }
{
std::cout << "lower_bound for a non-const object with requires is called.\n";
return container.lower_bound( key );
}


template <typename Container, typename Key>
auto lower_bound( const Container &container, const Key &key )
{
std::cout << "lower_bound for a const object without requires is called.\n";
return std::lower_bound( std::begin( container ), std::end( container ), key );
}

template <typename Container, typename Key >
auto lower_bound( Container &container, const Key &key )
{
std::cout << "lower_bound for a non-const object without requires is called.\n";
return std::lower_bound( std::begin( container ), std::end( container ), key );
}

template <typename Container, typename Key, typename Compare>
auto lower_bound( const Container &container, const Key &key, Compare comp )
{
std::cout << "lower_bound for a const object without requires is called.\n";
return std::lower_bound( std::begin( container ), std::end( container ), key, comp );
}

template <typename Container, typename Key, typename Compare>
auto lower_bound( Container &container, const Key &key, Compare comp )
{
std::cout << "lower_bound for a non-const object without requires is called.\n";
return std::lower_bound( std::begin( container ), std::end( container ), key, comp );
}

int main()
{
std::set<int> set1 = { 1, 2, 3, 4, 5 };
int value = 4;

auto it1 = lower_bound( set1, value );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( set1 ), it1 )
<< '\n';

const std::set<int> set2 = { 1, 2, 3, 4, 5 };

auto it2 = lower_bound( set2, value );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( set2 ), it2 )
<< '\n';

std::cout << '\n';

std::vector<int> v1 = { 1, 2, 3, 4, 5 };

auto it3 = lower_bound( v1, value );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( v1 ), it3 )
<< '\n';

const std::vector<int> v2 = { 1, 2, 3, 4, 5 };

auto it4 = lower_bound( v2, value );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( v2 ), it4 )
<< '\n';

std::cout << '\n';

std::vector<int> v3 = { 1, 2, 3, 4, 5 };

auto it5 = lower_bound( v3, value, std::less<>() );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( v3 ), it5 )
<< '\n';

const std::vector<int> v4 = { 1, 2, 3, 4, 5 };

auto it6 = lower_bound( v4, value, std::less<>() );

std::cout << "The position for " << value
<< " is " << std::distance( std::begin( v4 ), it6 )
<< '\n';

std::cout << '\n';
}

Вывод программы на консоль
 
lower_bound for a non-const object with requires is called.
The position for 4 is 3
lower_bound for a const object with requires is called.
The position for 4 is 3

lower_bound for a non-const object without requires is called.
The position for 4 is 3
lower_bound for a const object without requires is called.
The position for 4 is 3

lower_bound for a non-const object without requires is called.
The position for 4 is 3
lower_bound for a const object without requires is called.
The position for 4 is 3


Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 30.11.18 18:45. Заголовок: Будет более правильн..


Будет более правильным определить обобщенные функции std::sort и std::reverse таким образом, чтобы они возвращали ссылку на исходный контейнер.

Рассмотрите, к примеру, следующий вопрос начинающего программиста на сайте Stackoverflow Checking if two strings are anagram

В указанном вопросе требуется проверить, являются ли две строки анаграммами друг друга.

Один из подходов решения поставленной задачи - это сортировать строки и сравнить их друг с другом.

Написать соответствующую функцию будет очень просто, если обобщенная функция std::sort (это также касается и обобщенной функции std::reverse) будет возвращать ссылку на исходный контейнер.

Ниже представлена демонстрационная программа.
 
#include <iostream>
#include <iomanip>
#include <string>
#include <iterator>
#include <algorithm>

template <typename Container>
Container & sort( Container &container ) requires requires() { &Container::sort; }
{
container.sort();

return container;
}

template <typename Container>
Container & sort( Container &container )
{
std::sort( std::begin( container ), std::end( container ) );

return container;
}

bool isAnagrams( std::string s1, std::string s2 )
{
return std::size( s1 ) == std::size( s2 ) and sort( s1 ) == sort( s2 );
}

int main()
{
std::cout << "Enter two strings: ";

std::string s1, s2;

std::cin >> s1 >> s2;

std::cout << "The strings " << std::quoted( s1 )
<< " and " << std::quoted( s2 )
<< " are " << ( isAnagrams( s1, s2 ) ? "" : "not" )
<< " anagrams of each other.\n";
}

Ее вывод на консоль может выглядеть, к примеру, следующим образом:
 
Enter two strings: act tac
The strings "act" and "tac" are anagrams of each other.


Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 31
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет