printSTL

printВариативные типы

Тип optional<T> представляет собой объединение типов T и void, т.е. значение может отсутствовать. Может быть использован при работе с базами данных (аналог NULL) или для уменьшения количества исключений. Пусть функция intersect должна вернуть координаты точки пересечения двух отрезков. Можно написать функцию так:
Point intersect(Segment s1, Segment s2) {
  if(/*есть пересечение*/) { ... return {x,y};}
  else throw nointersect();
}
...
try {
  auto p=intersect(s1,s2);
  // обработка пересечения (p.x, p.y)
}
catch(nointersect&) {
  // обработка отсутствия пересечения
}
Формально функция написана правильно и возращает либо Point, либо nointersect, но обработка результата вызова нарушает логику программы. При использовании optional логика программы записывается более привычно через if:
optional<Point> intersect(Segment s1, Segment s2) {
  if(/*есть пересечение*/) { ... return Point{x,y};}
  else return {}; // или std::nullopt
}
...
if(auto p=intersect(s1,s2))
  // обработка пересечения (p->x, p->y), *p
}
else {
  // обработка отсутствия пересечения
}
Метод value_or возвращает значение или аргумент метода, если значение отсутствует.
Вместо небезопасного union в C++ предлагается тип variant<T1,T2,...>.
variant<int,double,string> v(1);
if(holds_alternative<int>(v)) {
  int i=get<int>(v);
}
try { 
  double d=get<double>(v); // исключение
}
catch (bad_variant_access&) {}
Тип any позволяет хранить значение любого типа.
any a = 1;
int i=any_cast<int>(a); // OK
try {
  auto s=any_cast<double>(a); // исключение
}
catch(bad_any_cast&) {  }
if(a.type()==typeid(int)) {
  auto &r=any_cast<int&>(a); // ссылка на значение или исключение
  ++r;
}
if(int *p=any_cast<int>(&a)) { // указатель, если тип правильный
  ++*p;
}
loading