~~~~~~~~~~~~~~~~~~~~ Arc.Ask3.Ru ~~~~~~~~~~~~~~~~~~~~~ 
Номер скриншота №:
✰ 2566F3DA41E12A8760B9529313D4F69B__1716863880 ✰
Заголовок документа оригинал.:
✰ Tagged union - Wikipedia ✰
Заголовок документа перевод.:
✰ Tagged союз — Википедия ✰
Снимок документа находящегося по адресу (URL):
✰ https://en.wikipedia.org/wiki/Tagged_union ✰
Адрес хранения снимка оригинал (URL):
✰ https://arc.ask3.ru/arc/aa/25/9b/2566f3da41e12a8760b9529313d4f69b.html ✰
Адрес хранения снимка перевод (URL):
✰ https://arc.ask3.ru/arc/aa/25/9b/2566f3da41e12a8760b9529313d4f69b__translat.html ✰
Дата и время сохранения документа:
✰ 13.06.2024 17:58:06 (GMT+3, MSK) ✰
Дата и время изменения документа (по данным источника):
✰ 28 May 2024, at 05:38 (UTC). ✰ 

~~~~~~~~~~~~~~~~~~~~~~ Ask3.Ru ~~~~~~~~~~~~~~~~~~~~~~ 
Сервисы Ask3.ru: 
 Архив документов (Снимки документов, в формате HTML, PDF, PNG - подписанные ЭЦП, доказывающие существование документа в момент подписи. Перевод сохраненных документов на русский язык.)https://arc.ask3.ruОтветы на вопросы (Сервис ответов на вопросы, в основном, научной направленности)https://ask3.ru/answer2questionТоварный сопоставитель (Сервис сравнения и выбора товаров) ✰✰
✰ https://ask3.ru/product2collationПартнерыhttps://comrades.ask3.ru


Совет. Чтобы искать на странице, нажмите Ctrl+F или ⌘-F (для MacOS) и введите запрос в поле поиска.
Arc.Ask3.ru: далее начало оригинального документа

Tagged союз — Википедия Jump to content

Теговый союз

Из Википедии, бесплатной энциклопедии

В информатике , тегированное объединение также называемое вариантом , вариантной записью , типом выбора , дискриминируемым объединением , непересекающимся объединением , типом суммы или копроизведением , представляет собой структуру данных, используемую для хранения значения, которое может принимать несколько разных, но фиксированных значений. типы. Одновременно может использоваться только один из типов, а поле тега явно указывает, какой тип используется. Его можно рассматривать как тип, имеющий несколько «случаев», каждый из которых должен корректно обрабатываться при манипулировании этим типом. Это имеет решающее значение при определении рекурсивных типов данных, в которых некоторый компонент значения может иметь тот же тип, что и это значение, например, при определении типа для представления деревьев , где необходимо различать многоузловые поддеревья и листья. Как и обычные объединения , тегированные объединения могут экономить место, перекрывая области хранения для каждого типа, поскольку одновременно используется только один из них.

Описание [ править ]

Теговые объединения наиболее важны в языках функционального программирования , таких как ML и Haskell , где они называются типами данных (см. Алгебраический тип данных ), и компилятор может проверить, что все случаи тегового объединения всегда обрабатываются, избегая многих типов ошибок. Типы проверяемых сумм во время компиляции также широко используются в Rust , где они называются enum . Однако их можно сконструировать практически на любом языке программирования , и они намного безопаснее, чем немаркированные объединения, часто называемые просто объединениями, которые похожи, но не отслеживают явно, какой член объединения используется в данный момент.

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

Математически тегированные союзы соответствуют непересекающимся или дискриминируемым союзам , обычно записываемым с помощью +. По элементу непересекающегося союза A + B можно определить, произошел ли он A или B. из Если элемент находится в обоих, будут две фактически различные копии значения в A + B одна из A и одна из B. :

В теории типов тегированное объединение называется типом суммы . Типы сумм являются двойственными типами продуктов . Обозначения различаются, но обычно тип суммы A + B имеет две формы введения ( инъекции ) inj 1 : A A + B и inj 2 : B A + B . Форма исключения — это анализ случаев, известный как сопоставление с образцом в языках ML : если e имеет тип A + B , а e 1 и e 2 имеют тип в предположениях x : A и y : B соответственно, то член имеет тип . Тип суммы соответствует интуиционистской логической дизъюнкции при соответствии Карри-Ховарда .

Перечислимый тип можно рассматривать как вырожденный случай: тегированное объединение типов единиц . Он соответствует набору нулевых конструкторов и может быть реализован как простая переменная тега, поскольку он не содержит никаких дополнительных данных, кроме значения тега.

Многие методы программирования и структуры данных, включая веревку , отложенное вычисление , иерархию классов (см. ниже), арифметику произвольной точности , кодирование CDR , бит косвенности и другие виды тегированных указателей , обычно реализуются с использованием некоторого рода тегового объединения.

Объединение тегов можно рассматривать как простейший вид с самоописанием формата данных . Тег тегированного объединения можно рассматривать как простейший вид метаданных .

Преимущества и недостатки [ править ]

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

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

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

Иногда нетегированные объединения используются для выполнения преобразований между типами на уровне битов, что в C++ называется переинтерпретацией приведения. Теговые союзы не предназначены для этой цели; обычно новое значение присваивается при каждом изменении тега.

Многие языки в некоторой степени поддерживают универсальный тип данных , который включает в себя все значения всех других типов, и часто предоставляется способ проверить фактический тип значения универсального типа. Их иногда называют вариантами . Хотя универсальные типы данных по формальному определению сравнимы с тегированными объединениями, типичные теговые объединения включают относительно небольшое количество случаев, и эти случаи образуют разные способы выражения одной связной концепции, такой как узел структуры данных или инструкция. Кроме того, ожидается, что каждый возможный случай объединения тегов будет рассмотрен при его использовании. Значения универсального типа данных не связаны друг с другом, и не существует реального способа справиться со всеми ними.

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

где «value» и «err» — конструкторы типа объединения, A и B — допустимые типы результатов, а E — тип условий ошибки. Альтернативно, та же монада может быть описана с помощью return и двух дополнительных функций, fmap и join :

Примеры [ править ]

Допустим, мы хотим построить двоичное дерево целых чисел. В ML мы бы сделали это, создав такой тип данных:

 типов данных  дерево   =   Лист 
               |    Узел    (  int   *   дерево   *   дерево  ) 

Это объединение с тегами в двух случаях: один, лист, используется для завершения пути дерева и действует так же, как нулевое значение в императивных языках. Другая ветвь содержит узел, содержащий целое число, а также левое и правое поддерево. Leaf и Node — это конструкторы, которые позволяют нам создавать конкретное дерево, например:

Узел  (  5  ,   Узел  (  1  ,   Лист  ,   Лист  ),   Узел  (  3  ,   Лист  ,   Узел  (  4  ,   Лист  ,   Лист  ))) 

что соответствует этому дереву:

Дерево, созданное вышеуказанными конструкторами
The tree produced by the above constructors

Теперь мы можем легко написать типобезопасную функцию, которая, например, подсчитывает количество узлов в дереве:

весело   countNodes  (  Лист  )   =   0 
   |    countNodes  (  Node  (  int  ,   left  ,   right  ))   = 
       1   +   countNodes  (  слева  )   +   countNodes  (  справа  ) 

График языковой поддержки [ править ]

1960-е годы [ править ]

В АЛГОЛе 68 теговые объединения называются объединенными модами , тег является неявным, а case Конструкция используется для определения того, какое поле помечено:

mode node = union (real, int, compl, string);

Пример использования для union case из node:

узел  n:= "1234"; 
 
  случай  n  в 
    (  real  r): print(("real:", r)), 
    (  int  i): print(("int:", i)), 
    (  compl  c): print(("compl:", c)), 
    (  строка  s): print(("строка:", s)) 
    out  print(("?:", n)) 
  Эсак 

1970-е и 1980-е годы [ править ]

Языки функционального программирования , такие как ML (с 1970-х годов) и Haskell (с 1990-х годов), отводят центральную роль теговым объединениям и имеют возможность проверять обработку всех случаев. Некоторые другие языки также поддерживают теговые объединения.

Pascal , Ada и Modula-2 называют их вариантными записями (формально различаемый тип в Ada) и требуют, чтобы поле тега было создано вручную и указаны значения тега, как в этом примере Pascal:

введите   shapeKind   =   (  квадрат  ,   прямоугольник  ,   круг  )  ; 
       форма   =   запись 
                 centerx   :   целое число  ; 
                  центр   :   целое число  ; 
                 случая    Вид   :   формаВид   квадрата 
                    (   :   число  сторона   :   целое  )  ; 
                     прямоугольник   :   (  ширина  ,   высота   :   целое число  )  ; 
                     круг   :   (  радиус   :   целое число  )  ; 
	        конец  ; 

и этот эквивалент Ada:

тип   Shape_Kind   (   Квадрат  Прямоугольник  ,   ,  )   Круг  ; 
  тип   Shape   (  Kind   :  Shape_Kind  )    запись 
    Center_X   :   Integer  ; 
     Center_Y   :   Целое число  ; 
     Case   Kind   — это 
       когда   Square   => 
          Side   :   Integer  ; 
        когда   Прямоугольник   => 
          Ширина  ,   Высота   :   Целое число  ; 
        когда   Круг   => 
          Радиус   :   Целое число  ; 
     конец   дела  ; 
  завершить запись  ; 

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

В C и C++ тегированный союз может быть создан из нетегированного объединения с использованием строгой дисциплины доступа, при которой тег всегда проверяется:

enum   ShapeKind   {   Квадрат  ,   Прямоугольник  ,   Круг   }; 

  структура   Shape   { 
     int   centerx  ; 
      интервал по   центру  ; 
      перечисление   ShapeKind   kind  ; 
      объединение   { 
         структура   {   int   сторона  ;    };              /* Square */ 
         struct   {   int   width  ,   height  ;    };    /* Прямоугольник */ 
         struct   {   int   radius  ;    };            /* Круг */ 
     }; 
  }; 

  int   getSquareSide  (  struct   Shape  *   s  )   { 
     assert  (  s  ->  kind   ==   Square  ); 
      вернуть   s  ->  сторона  ; 
  } 

 void   setSquareSide  (  struct   Shape  *   s  ,   intside   )  ;   { 
     s  >  kind   =   Square  - 
      s  ->  сторона   =   сторона  ; 
  } 

 /* и так далее */ 

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

В C и C++ также имеется языковая поддержка одного конкретного объединения тегов: возможно нулевого указателя . Это можно сравнить с option введите ML или Maybe введите в Haskell и его можно рассматривать как тегированный указатель : тегированное объединение (с закодированным тегом) двух типов:

  • Действительные указатели,
  • Тип нулевого указателя только с одним значением, null, что указывает на исключительное состояние.

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

2000-е [ править ]

Один из продвинутых диалектов C, называемый Cyclone , имеет обширную встроенную поддержку теговых объединений. [1]

Типы перечислений в языках Rust , Haxe и Swift также работают как тегированные объединения.

Библиотека вариантов из библиотек Boost C++ продемонстрировала возможность реализации безопасного объединения тегов в виде библиотеки на C++, доступной для посещения с использованием объектов-функций.

struct   display   :   boost  ::  static_visitor  <  void  > 
 { 
     void   оператор  ()(  int   i  ) 
     { 
         std  ::  cout   <<   "Это int со значением "   <<   i   <<   std  ::  endl  ; 
      } 

     void   оператор  ()(  const   std  ::  string  &   s  ) 
     { 
         std  ::  cout   <<   "Это строка со значением "   <<   s   <<   std  ::  endl  ; 
      } 
 }; 

  boost  ::  variant  <  int  ,   std  ::  string  >   v   =   42  ; 
  boost  ::  apply_visitor  (  display  (),   v  ); 

  boost  ::  variant  <  int  ,   std  ::  string  >   v   =   "привет, мир"  ; 
  boost  ::  apply_visitor  (  display  (),   v  ); 

В Scala есть классы случаев:

запечатанный   абстрактный   класс   Tree 
 Case   Объект   Leaf   расширяет   Tree 
 Case   класс   Node  (  значение  :   Int  ,   слева  :   Tree  ,   справа  :   Tree  )   расширяет   Tree 

 val   Tree   =   Node  (  5  ,   Node  (  1  ,   Leaf  ,   Leaf  ),   Node  (  3  ,   Leaf  ,   Node )  (  4  ,   Лист  ,   Лист  ))) 

Поскольку иерархия классов изолирована, компилятор может проверить, что все случаи обрабатываются в соответствии с шаблоном:

 дерева  сопоставление   { 
   case   Node  (  x  ,   _  ,   _  )   =>   println  (  «значение узла верхнего уровня: «   +   x  ) 
   case   Leaf            =>   println  (  «узел верхнего уровня является листом»  ) 
 } 

Классы Scala также допускают повторное использование посредством подтипирования:

запечатанный   абстрактный   класс   Shape  (  centerX  :   Int  ,   centerY  :   Int  ) 
 случая   класс   Square  (  сторона  :   Int  ,   centerX  :   Int  ,   centerY  :   Int  )   расширяет   форму  (  centerX  ,   centerY  ) 
 корпуса   класс   Rectangle  (  длина  :   Int  ,   высота  :   Int  ,   centerX  :   Int  ,   centerY  :   Int  )   расширяет   форму  (  centerX  ,   centerY  ) 
 корпуса   класс   Circle  (  радиус  :   Int  ,   centerX  :   Int  ,   centerY  :   Int  )   расширяет   форму  (  centerX  ,   centerY  ) 

В F# есть дискриминационные союзы:

тип   Дерево   = 
   |    Лист 
   |    Узел   значения   Leaf  :   int   *   left  :   Tree   *   right  :   Tree 

 let   Tree   =   Node  (  5  ,   Node  (  1  ,   Leaf  ,   (  ,   Node  (  3  ,   Leaf  ,   Node  4  )  ,   Leaf  ,   Leaf  )) 

Поскольку определенные случаи являются исчерпывающими, компилятор может проверить, что все случаи обрабатываются в соответствии с шаблоном:

 совпадений  дерево   с 
 |    Узел   (  x  ,   _,   _)   ->   printfn   «значение узла верхнего уровня: %i»   x 
 |    Leaf             ->   printfn   «узел верхнего уровня является листом» 

: Перечисления Haxe также работают как тегированные объединения [2]

перечисление   Цвет   { 
   Красный  ; 
    Зеленый  ; 
    Синий  ; 
    Rgb  (  r  :  Int  ,   g  :  Int  ,   b  :  Int  ); 
  } 

Их можно сопоставить с помощью выражения переключателя:

переключатель   (  цвет  )   { 
   case   Red  :   трассировка  (  «Цвет был красный»  ); 
    case   Green  :   трассировка  (  «Цвет был зеленый»  ); 
    case   Blue  :   трассировка  (  «Цвет был синий»  ); 
    case   Rgb  (  r  ,   g  ,   b  ):   трассировка  (  «Цвет имел красное значение «   +  r  ); 
  } 

У Нима есть варианты объектов [3] объявление аналогично объявлениям в Паскале и Аде:

тип 
   ShapeKind   =   enum 
     skSquare  ,   skRectangle  ,   skCircle 
   Shape   =   объект 
     centerX  ,   centerY  :   int 
     случая   тип  :   ShapeKind 
     из   skSquare  : 
       сторона  :   int 
     из   skRectangle  : 
       длина  ,   высота  :   int 
     из   skCircle  : 
       радиус  :   int 

Макросы можно использовать для эмуляции сопоставления с образцом или для создания синтаксического сахара для объявления вариантов объекта, как показано здесь, как это реализовано пакетом patty :

import   patty 

 proc   `~`  [  A  ]  (  a  :   A  ):   A   =   новый 
   (  result  )  result 
   [  ]   =   вариант 

 A   List  [  A  ]  : 
   Nil 
   Cons  (  x  :   ,  ref   xs  :   ref   List  [  A  ]  ) 

 proc   listHelper  [  A  ]  (  xs  :   seq  [  A  ]  ):   Список  [  A  ]   = 
   if   xs  .   len   ==   0  :   Nil  [  A  ]  () 
   else  :   Cons  (  xs  [  0  ]  ,   ~  listHelper  (  xs  [  1   ..   xs  .  high  ]  )) 

 процедур   список  [  A  ]  (  xs  :   varargs  [  A  ]  ):   List  [  A  ]   =   listHelper  (  @  xs  ) 

 proc   sum  (  xs  :   List  [  int  ]  ):   int   =   (  блок  : 
   match   xs  : 
     Nil  :   0 
     Cons  (  y  ,   ys  ):   y   +   sum  (  ys  []  ) 
 ) 

 echo   sum  (  список  (  1  ,   2  ,   3  ,   4  ,   5  )) 

2010-е [ править ]

Перечисления добавлены в Scala 3, [4] что позволяет нам более кратко переписать предыдущие примеры Scala:

enum   Tree  [  +  T  ]: 
   регистр   Leaf 
   Case   Node  (  x  :   Int  ,   слева  :   Tree  [  T  ],   справа  :   Tree  [  T  ]) 

 enum   Shape  (  centerX  :   Int  ,   centerY  :   Int  ): 
   case   Square  (  сторона  :   Int  ,   centerX  :   Int  ,   centerY  :   Int  )   расширяет   Shape  (  centerY  ,   centerX  ) 
   регистр   Прямоугольник  (  длина  :   Int  ,   высота  :   Int  ,   centerX  :   Int  ,   centerY  :   Int  )   расширяет   Shape  (  centerX  ,   centerY  ) 
   регистр   Круг  (  радиус  :   Int  ,   centerX  :   Int)  ,   centerY  :   Int  )   расширяет   форму  (  centerX  ,   centerY  ) 

В языке Rust имеется обширная поддержка объединений тегов, называемых перечислениями. [5] Например:

enum   Tree   { 
     Лист  , 
     Узел  (  i64  ,   Box  <  Дерево  >  ,   Box  <  Дерево  >  ) 
 } 

Он также позволяет сопоставлять союзы:

let   Tree   =   Дерево  ::  Узел  ( 
     2  , 
     Коробка  ::  новый  (  Дерево  ::  Узел  (  0  ,   Коробка  ::  новый  (  Дерево  ::  Лист  ),   Коробка  ::  новый  (  Дерево  ::  Лист  ))), 
     Коробка  ::  новый  (  Дерево  ::  Узел  (  3  ,   Коробка  ::  новый  (  Дерево  ::  Лист  ), 
         Коробка  ::  новый  (  Дерево  ::  Узел  (  4  ,   Коробка  ::  новый  (  Дерево  ::  Лист  ),   Коробка  ::  новый  (  Дерево  ::  Лист  ))))) 
 ); 

  fn   add_values  ​​(  tree  :  Tree  )   ->  i64   { 
     match   Tree   { 
         Tree  ::  Node  (  v  ,   a  ,   b  )   =>   v   +   add_values  ​​(  *  a  )   +   add_values  ​​(  *  b  ), 
         Tree  ::  Leaf   =>   0 
     } 
 } 

 утверждать_eq!   (  add_values  ​​(  дерево  ),   9  ); 

Модель обработки ошибок в Rust во многом опирается на эти теговые объединения, особенно на Option<T> тип, который либо None или Some(T)и Result<T, E> тип, который либо Ok(T) или Err(E). [6]

Swift также имеет существенную поддержку тегированных объединений посредством перечислений. [7] Например:

enum   Tree   { 
     случая   лист 
     косвенный   случая   узел  (  Int  ,   Tree  ,   Tree  ) 
 } 

 let   Tree   =   Tree  .   узел  ( 
     2  , 
     .узел  0  (  ,  ,   .лист  .лист  ,   4  ,  ) 
     ,.  узел  (  3  ,   .лист  Tree  .узел   )  .лист  (  .лист   ,  Int   переключатель  ) 
 ) 

 func   add_values  (  _tree   :  >    -    { 
      дерево   { 
     случай   пусть   .   узел  (  v  ,   a  ,   b  ): 
         return   v   +   add_values  ​​(  a  )   +   add_values  ​​(  b  ) 

     case   .   лист  : 
         вернуть   0 
     } 
 } 

 утверждать  (  add_values  ​​(  дерево  )   ==   9  ) 

С помощью TypeScript также можно создавать теговые объединения. Например:

интерфейс   Leaf   {   kind  :   "leaf"  ;    } 

 интерфейса   Узел   {   вид  :   "узел"  ;    значение  :   число  ;    слева  :   Дерево  ;    справа  :   Дерево  ;    } 

 Тип   Дерево   =   Лист   |   узла 

  Константный   корень  :   Дерево   =   { 
   вид  :   "узел"  , 
   значение  :   5  , 
   влево  :   { 
     вид  :   "узел"  , 
     значение  :   1  , 
     влево  :   {   вид  :   "лист"   }, 
     вправо  :   {   вид  :   "лист"   } 
   } , 
   вправо  :   { 
     вид  :   "узел"  , 
     значение  :   3  , 
     влево  :   {   вид  :   "лист"   }, 
     вправо  :   { 
       вид  :   "узел"  , 
       значение  :   4  , 
       влево  :   {   вид  :   "лист"   }, 
       вправо  :   {   вид  :   "лист"   } 
     } 
   } 
 } 

 функция   посещения  (  дерево  :   Дерево  )   { 
     переключатель   (  дерево  .  вид  )   { 
         случай   "лист"  : 
             разрыв 
         случая   "узел"  : 
             консоль  .   журнал  (  дерево  .  значение  ) 
             посещение  (  дерево  .  влево  ) 
             посещение  (  дерево  .  вправо  ) 
             перерыв  
     }  
 } 

В Python 3.9 появилась поддержка ввода аннотаций, которые можно использовать для определения типа объединения тегов (PEP-593). [8] ):

Валюта   =   Аннотация  [ 
     TypedDict  (  'Currency'  ,   {  'доллары'  :   float  ,   'фунты'  :   float  },   total  =  False  ), 
     TaggedUnion  , 
 ] 

В C++17 представлены std::variant и constexpr, если

используя   Tree   =   std  ::  variant  <  struct   Leaf  ,   struct   Node  >  ; 

  struct   Leaf 
 { 
   std  ::  строковое   значение  ; 
  }; 
  struct   Node 
 { 
   Дерево  *   left   =   nullptr  ; 
    Дерево  *   вправо   =   nullptr  ; 
  }; 

  struct   Transverser 
 { 
   шаблон  <  имя типа   T  > 
   void   оператор  ()(  T  &&   v  ) 
   { 
     if   constexpr   (  std  ::  is_same_v  <  T  ,   Leaf  &>  ) 
     { 
       std  ::  cout   <<   v  .   значение   <<   "  \n  "  ; 
      } 
     else   if   constexpr   (  std  ::  is_same_v  <  T  ,   Node  &>  ) 
     { 
       if   (  v  .  left   !=   nullptr  ) 
         std  ::  visit  (  Transverser  {},   *  v  .  left  ); 

        if   (  v  .  right   !=   nullptr  ) 
         std  ::  visit  (  Transverser  {},   *  v  .  right  ); 
      } 
     else 
     { 
       // Выражение !sizeof(T) всегда ложно 
       static_assert  (  !  sizeof  (  T  ),   "неполный посетитель!"  ); 
      }; 
    } 
 }; 
  /*Деревянный лес = ...; 
  std::visit(Transverser{}, Forest);*/ 

Иерархии классов как тегированные объединения [ править ]

типичной иерархии классов В объектно-ориентированного программирования каждый подкласс может инкапсулировать данные, уникальные для этого класса. Метаданные, используемые для поиска виртуальных методов объекта (например, указатель vtable в большинстве реализаций C++), идентифицируют подкласс и поэтому эффективно действуют как тег, идентифицирующий данные, хранящиеся в экземпляре (см. RTTI ). объекта Конструктор устанавливает этот тег, и он остается постоянным на протяжении всего существования объекта.

Тем не менее, иерархия классов предполагает истинный полиморфизм подтипов . Его можно расширить путем создания дополнительных подклассов того же базового типа, которые невозможно правильно обработать в рамках модели тегов/отправки. Следовательно, обычно невозможно выполнить анализ вариантов или отправку «тега» подобъекта, как это было бы в случае с тегированными объединениями. Некоторые языки, такие как Scala, позволяют «запечатывать» базовые классы и объединять тегированные объединения с запечатанными базовыми классами.

См. также [ править ]

Ссылки [ править ]

  1. ^ «Циклон: Союзы с тегами» .
  2. ^ «Использование перечислений — Haxe — кроссплатформенный набор инструментов» . Фонд Хаксе.
  3. ^ «Руководство Нима» . nim-lang.org . Проверено 23 января 2020 г.
  4. ^ «Справочник по языку Scala 3: перечисления» . Команда Скала.
  5. ^ «Язык программирования Rust» . Мозилла.
  6. ^ «Ржавчина на примере» . Мозилла.
  7. ^ «Перечисления — язык программирования Swift (Swift 5.4)» . docs.swift.org . Проверено 28 апреля 2021 г.
  8. ^ «PEP 593 — Гибкие функции и аннотации переменных» . Python.org . Проверено 20 июня 2021 г.

Внешние ссылки [ править ]

  • boost::variant — это типобезопасное дискриминируемое объединение C++.
  • std.variant — это реализация варианта типа в D 2.0.
Arc.Ask3.Ru: конец оригинального документа.
Arc.Ask3.Ru
Номер скриншота №: 2566F3DA41E12A8760B9529313D4F69B__1716863880
URL1:https://en.wikipedia.org/wiki/Tagged_union
Заголовок, (Title) документа по адресу, URL1:
Tagged union - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть, любые претензии не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, денежную единицу можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)