Дослідження std::any та std::variant у сучасному C++

C++ | Поради

pic

вступ

З розвитком C++ та впровадженням std::any і std::variant у C++17 були додані потужні інструменти для обробки гнучкого зберігання типів і типово-безпечних альтернатив. У цьому пості ми розглянемо ці два інструменти, дослідимо їхні відмінності та зрозуміємо, як ефективно їх використовувати.

Що таке std::any?

std::any є частиною Стандартної бібліотеки шаблонів (STL) і призначена для зберігання значень будь-якого типу. Вона дозволяє зберігати і отримувати типи під час виконання програми, що робить її дуже гнучким інструментом для ситуацій, коли тип невідомий під час компіляції.

Основні характеристики std::any:

  • Може зберігати значення будь-якого типу.
  • Потрібні перевірки типів під час виконання для отримання збереженого значення.
  • Гнучка, але менш продуктивна, ніж типово-безпечні альтернативи, такі як std::variant.

Як використовувати std::any:

#include <any>
#include <iostream>

int main() {  
 std::any value;  

 // Зберігаємо ціле число  
 value = 2;  
 std::cout << "Збережене ціле число: " << std::any_cast<int>(value) << "\n";  

 // Зберігаємо рядок  
 value = std::string("Привіт, Світ!");  
 std::cout << "Збережений рядок: " << std::any_cast<std::string>(value) << "\n";  

 return 0;  
}
Збережене ціле число: 2  
Збережений рядок: Привіт, Світ!

У наведеному прикладі std::any зберігає спочатку ціле число, а потім рядок. Для безпечного отримання значення використовується std::any_cast. Якщо ви спробуєте отримати значення невідповідного типу, буде викинуто виключення std::bad_any_cast.

Коли використовувати std::any:

  • Коли потрібно зберігати значення довільних типів.
  • Коли типова безпека не є строгим вимогам.

Що таке std::variant?

std::variant є типово-безпечною альтернативою об'єднанням, введена в C++17. На відміну від std::any, std::variant може зберігати лише одне значення одночасно, але це значення повинно бути одним із попередньо визначених типів.

Основні характеристики std::variant:

  • Типово-безпечний під час компіляції.
  • Без накладних витрат на перевірку типів під час виконання.
  • Підтримує шаблонне узгодження за допомогою std::visit для чистого оброблення різних типів.

Як використовувати std::variant:

#include <variant>
#include <iostream>

int main() {  
 std::variant<int, std::string> var;  

 // Призначаємо ціле число  
 var = 10;  
 std::cout << "Ціле число в variant: " << std::get<int>(var) << "\n";  

 // Призначаємо рядок  
 var = "Привіт, Variant!";  
 std::cout << "Рядок в variant: " << std::get<std::string>(var) << "\n";  

 return 0;  
}
Ціле число в variant: 10  
Рядок в variant: Привіт, Variant!

Шаблонне узгодження з std::variant:

Однією з найпотужніших функцій std::variant є шаблонне узгодження з використанням std::visit. Це дозволяє обробляти кожен можливий тип чітко:

#include <variant>
#include <iostream>

int main() {  
 std::variant<int, std::string> var = "Шаблонне узгодження";  

 std::visit([](auto&& arg) {  
 std::cout << "Значення: " << arg << "\n";  
 }, var);  

 return 0;  
}

Тут std::visit автоматично визначає тип, який зараз зберігається у variant, і виконує відповідну логіку.

Коли використовувати std::variant:

  • Коли потрібно зберігати одне значення з попередньо визначеного набору типів.
  • Коли потрібна типова безпека і бажано уникати помилок під час виконання.

Основні відмінності між std::any та std::variant

pic

Практичні випадки використання

Коли вибрати std::any:

  • Реалізація фреймворків для логування, що повинні обробляти довільні типи.
  • Загальні контейнери, що зберігають гетерогенні дані.

Коли вибрати std::variant:

  • Моделювання переходів станів у скінчених автоматах.
  • Обробка тегованих об'єднань з типово-безпечними способами.

Висновок

Обидва інструменти std::any та std::variant є потужними засобами, введеними в C++17, кожен з яких має свої переваги. Використовуйте std::any для гнучкості, коли типи невідомі під час компіляції.
Використовуйте `` для безпеки типів під час компіляції та кращої продуктивності. Розуміння їхніх відмінностей та випадків використання дозволяє писати більш надійний та підтримуваний код на C++.

Перекладено з: Exploring std::any and std::variant in Modern C++

Leave a Reply

Your email address will not be published. Required fields are marked *