Kniga-Online.club
» » » » C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

Читать бесплатно C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц. Жанр: Программирование год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:
class="p1">  static std::string& standard_string() {

    static std::string s {"some standard string"};

    return s;

  }

};

Подобным образом вы можете совершенно легально включить заголовочный файл в несколько модулей и при этом получать доступ к одному и тому же экземпляру отовсюду. Однако объект не создается немедленно при старте программы — это происходит только при первом вызове функции-геттера. В некоторых случаях это может оказаться проблемой. Представьте, будто нужно, чтобы конструктор статического объекта, доступного глобально, при запуске программы выполнял некую важную операцию (в точности как наш класс-пример), но мы не получаем желаемого из-за вызова геттера ближе к концу программы.

Проблему можно решить еще одним способом: сделав класс foo шаблонным и воспользовавшись преимуществами шаблонов.

В C++17 оба варианта становятся неактуальны. 

Реализуем вспомогательные функции с помощью выражений свертки

 Начиная с C++11, в языке появились пакеты параметров для шаблонов с переменным количеством аргументов. Такие пакеты позволяют реализовывать функции, принимающие переменное количество параметров. Иногда эти параметры объединяются в одно выражение, чтобы на его основе можно было получить результат работы функции. Решение этой задачи значительно упростилось с выходом C++17, где появились выражения свертки.

Как это делается

Реализуем функцию, которая принимает переменное количество параметров и возвращает их сумму.

1. Сначала определим ее сигнатуру:

template <typename Ts>

auto sum(Ts ts);

2. Теперь у нас есть пакет параметров ts, функция должна распаковать все параметры и просуммировать их с помощью выражения свертки. Допустим, мы хотим воспользоваться каким-нибудь оператором (в нашем случае +) вместе с ..., чтобы применить его ко всем значениям пакета параметров. Для этого нужно взять выражение в скобки:

template <typename Ts>

auto sum(Ts ts)

{

  return (ts + ...);

}

3. Теперь можно вызвать функцию следующим образом:

int the_sum {sum(1, 2, 3, 4, 5)}; // Значение: 15

4. Она работает не только с целочисленными типами; можно вызвать ее для любого типа, реализующего оператор +, например std::string:

std::string a {"Hello "};

std::string b {"World"};

std::cout << sum(a, b) << 'n'; // Вывод: Hello World

Как это работает

Только что мы написали код, в котором с помощью простой рекурсии бинарный оператор (+) применяется к заданным параметрам. Как правило, это называется сверткой. В C++17 появились выражения свертки, которые помогают выразить ту же идею и при этом писать меньше кода.

Подобное выражение называется унарной сверткой. C++17 позволяет применять к пакетам параметров свертки следующие бинарные операторы: +, –, *, /, %, ^, &, |,

=, <, >, <<, >>, +=, –=, *=, /=, %=, ^=, &=, |=, <<=, >>=, ==, !=, <=, >=, &&, ||, ,, .*, –>*.

Кстати, в нашем примере кода неважно, какую использовать конструкцию, (ts + …) или (… + ts);. Они обе работают так, как нужно. Однако между ними есть разница, которая может иметь значение в других случаях: если многоточие … находится с правой стороны оператора, то такое выражение называется правой сверткой. Если же оно находится с левой стороны, то это левая свертка.

В нашем примере с суммой левая унарная свертка разворачивается в конструкцию 1+(2+(3+(4+5))), а правая унарная свертка развернется в (((1+2)+3)+4)+5. В зависимости от того, какой оператор используется, могут проявиться нюансы. При добавлении новых чисел ничего не меняется.

Дополнительная информация

Если кто-то вызовет функцию sum() и не передаст в нее аргументы, то пакет параметров произвольной длины не будет содержать значений, которые могут быть свернуты. Для большинства операторов такая ситуация считается ошибкой (но для некоторых — нет, вы увидите это чуть позже). Далее нужно решить, генерировать ошибку или же вернуть конкретное значение. Очевидным решением будет вернуть значение 0.

Это делается так:

template <typename ... Ts>

auto sum(Ts ... ts)

{

  return (ts + ... + 0);

}

Таким образом, вызов sum() возвращает значение 0, а вызов sum(1, 2, 3) — значение (1+(2+(3+0))). Подобные свертки с начальным значением называются бинарными.

Кроме того, обе конструкции, (ts + ... + 0) и (0 + ... + ts), работают как полагается, но такая бинарная свертка становится правой или левой соответственно. Взгляните на рис. 1.2.

При использовании бинарных сверток для решения такой задачи, когда аргументы отсутствуют, очень важны нейтральные элементы — в нашем случае сложение любого числа с нулем ничего не меняет, что делает 0 нейтральным элементом. Поэтому можно добавить 0 к любому выражению свертки с помощью операторов + или –. Если пакет параметров пуст, это приведет к возврату функцией значения 0. С математической точки зрения это правильно. С точки зрения реализации нужно определить, что именно является правильным в зависимости от наших требований.

Тот же принцип применяется и к умножению. Здесь нейтральным элементом станет 1:

template <typename Ts>

auto product(Ts ts)

{

  return (ts * ... * 1);

}

Результат вызова product(2, 3) равен 6, а результат вызова product() без параметров равен 1.

В логических операторах И (&&) и ИЛИ (||) появились встроенные нейтральные элементы. Свертка пустого пакета параметров с оператором && заменяется на true, а свертка пустого пакета с оператором || — на false.

Еще один оператор, для которого определено значение по умолчанию, когда он используется для пустых пакетов параметров, — это оператор «запятая» (,), заменяемый на void().

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

Соотнесение диапазонов и отдельных элементов 

Как насчет функции, которая определяет, содержит ли диапазон хотя бы одно из значений, передаваемых в пакете параметров с переменной длиной:

template <typename R, typename ... Ts>

auto matches(const R& range, Ts ... ts)

{

  return (std::count(std::begin(range), std::end(range), ts) + ...);

}

Вспомогательная функция использует функцию std::count из библиотеки STL. Она принимает три параметра:

Перейти на страницу:

Яцек Галовиц читать все книги автора по порядку

Яцек Галовиц - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


C++17 STL Стандартная библиотека шаблонов отзывы

Отзывы читателей о книге C++17 STL Стандартная библиотека шаблонов, автор: Яцек Галовиц. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*