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

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



ссылка на сообщение  Отправлено: 06.02.15 12:33. Заголовок: std::advance и std::bitset - два простых предложения по стандарту C++


Порой простые, на первый взгляд совершенно незначительные изменения стандарта C++ позволяют существенно облегчить жизнь программистов. О двух таких предложениях по изменению стандарта C++, относящихся к функции std::advance и классу std::bitset, речь пойдет ниже.

В настоящий момент имеется три стандартные функции, которые предназначены для "перемещения" итераторов по элементам контейнера или последовательности.
Это функция std::advance, которая давно известна программистам по крайней мере с момента принятия стандарта C++ 2003, и две новые функции, std::next и std::prev, которые были включены в стандарт C++ 2011.

Например, чтобы получить следующую "позицию" итератора после текущей, можно написать следующим образом:
 
auto it2 = std::next( it1, 1 );

Очевидно, что в этом предложении второй аргумент в функции std::next избыточен. Для своего второго параметра функция имеет аргумент по умолчанию как раз равный 1. Поэтому будет проще и более выразительно написать:
  
auto it2 = std::next( it1 );

Это предложение более ясное и аккуратное.
Точно также функция std::prev имеет аргумент по умолчанию для своего второго параметра. Поэтому можно, например, записать
 
auto it2 = std::prev( it1 );

И только функция std::advance выбивается из общего ряда данных функций. Ее второй параметр не имеет аргумента по умолчанию. Поэтому вместо достаточно выразительного и ясного кода
 
std::advance( it1 );

вы вынуждены писать
 
std::advance( it1, 1 );

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

Поэтому логически последовательно было бы определить функцию std::advance точно таким же образом, как определены функции std::next и std::prev:
 
template <class InputIterator,
class Distance = typename std::iterator_traits<InputIterator>::difference_type>
void advance(InputIterator& i, Distance n = 1);

Если по каким-то своим личным соображениям вы все же хотите явно указывать 1 в качестве второго аргумента вызова функции, то данное объявление функции не будет препятствовать вам в этом.

Конечно вместо функции std::advance можно использовать оператор инкримента:
 
++it1;

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

Это мое предложение по изменению стандарта C++ получило номер документа №4369.

Очевидно, что трудно писать обобщенный и надежный код, если классы не будут предоставлять общую форму обращения к своим свойствам. Наверное самое распространенное свойство многих классов особенно контейнеров, это свойство size, задающее количество элементов в объекте или размер самого объекта. Для этого свойства обычно используется общая форма обращения, получившая название size_type. Например, в классе std::basic_string доступ к свойствам класса capacity и size определены следующим образом с использованием общей формы обращения size_type:
`
size_type size() const noexcept;
size_type capacity() const noexcept;
`

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

Рассмотрим следующий пример. Допустим в вашем проекте используется некоторое множество флагов, которые обрабатываются в некоторых методах или функциях проекта.
Для хранения флагов вы выбрали стандартный контейнер std::vector<bool>. Код вашего проекта структурно и логически может выглядеть следующим образом:
 
using special_flags_t = std::vector<bool>;

void method1( special_flags_t::size_type flag_number, bool flag_value )
{
// some processing using the flag
}

//...

void methodn( special_flags_t::size_type flag_number, bool flag_value )
{
// some processing using the flag
}

//...

special_flags_t flag_values;

//...

for ( special_flags_t::size_type flag_number = 0;
flag_number < flag_values.size();
flag_number++ )
{
method1( flag_number, flag_values[flag_number] );
}

//...

for ( special_flags_t::size_type flag_number = 0;
flag_number < flag_values.size();
flag_number++ )
{
methodn( flag_number, flag_values[flag_number] );
}

Однако через некоторое время эксплуатации программы вы пришли к заключению, что будет лучше заменить std::vector<bool> на класс std::bitset<N>, где N - некоторая предопределенная константа, так как множество флагов имеет небольшой фиксированный размер.

Так как вы старались писать свой код таким образом, чтобы он меньше всего зависел от деталей используемого контейнера для флагов, вы резонно расчитывали, что будет достаточно просто заменить в объявлении алиаса special_flags_t std::vector<bool> на std::bitset<N>, и это было бы действительно здорово, если все ваши изменения в проекте ограничивались только этой одной заменой. Однако если вместо
 
using special_flags_t = std::vector<bool>;

вы напишите
 
using special_flags_t = std::bitset<N>;

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

Проблема в том, что класс std::bitset не предоставляет общей формы обращения size_type к своему свойству size. Этот недостаток класса std::bitset препятствует написанию обобщенного и гибкого кода, независящего от деталей реализации используемых классов.

Поэтому вполне логично внести предложение по изменению стандарта C++, включив в определение класса std::bitset следующее определение:
 
namespace std {
template<size_t N> class bitset {
public:
typedef size_t size_type;

//,,,
};


Это мое предложение получило номер документа №4368.

Остается ждать, как отнесется к этим моим простым предложениям по изменению стандарта C++ Комитет по стандартизации.


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


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

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