{"id":374565,"date":"2024-05-21T06:03:26","date_gmt":"2024-05-21T06:03:26","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=374565"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=374565","title":{"rendered":"<span>\u0424\u0430\u0431\u0440\u0438\u043a\u0430 \u0434\u043b\u044f std::variant: \u043a\u0430\u043a \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c compile-time \u0438 run-time, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u043e\u0442 \u043e\u0431\u043e\u0438\u0445<\/span>"},"content":{"rendered":"<div><!--[--><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/vk.com\/rtrg?p=VK-RTRG-1297426-bEGLU&amp;event=habr_workspace\" style=\"display:none;\" width=\"1\"><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ov\/3i\/a0\/ov3ia0xugzrnqhniljsey55ozo8.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ov\/3i\/a0\/ov3ia0xugzrnqhniljsey55ozo8.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u0443\u043a\u0430\u0440\u043e\u0432, \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 Desktop-\u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0441 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 <a href=\"https:\/\/biz.mail.ru\/teams\/?utm_source=habr&amp;utm_medium=refferal&amp;utm_campaign=fabrica_dlya_std\">VK Teams<\/a>.\u00a0<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438, \u0433\u0434\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u043d\u0430\u0435\u0442\u0435 \u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0435\u0439 \u043b\u0430\u0432\u0438\u043d\u0435 \u043a\u043e\u0434\u0430. \u0422\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c, \u0438\u0437\u0443\u0447\u0430\u0442\u044c \u0438 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u041f\u043e\u0434\u0435\u043b\u044e\u0441\u044c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0421++, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u044c compile-time \u0438 run-time \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0432 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0421 \u043a\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u043c\u044b<\/h2>\n<p>  \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 <a href=\"https:\/\/biz.mail.ru\/teams\/?utm_source=habr&amp;utm_medium=refferal&amp;utm_campaign=fabrica_dlya_std\">VK Teams<\/a> \u0435\u0441\u0442\u044c \u0432\u0438\u0434\u0435\u043e\u0437\u0432\u043e\u043d\u043a\u0438. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0437\u0432\u043e\u043d\u0438\u0442\u044c 1:1, \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u0438\u043b\u0438 \u0432\u0435\u0431\u0438\u043d\u0430\u0440\u044b. \u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0432\u0441\u0442\u0430\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435\u043e \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432. \u0412\u0441\u0435 \u043e\u0441\u043b\u043e\u0436\u043d\u044f\u043b\u043e\u0441\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043c\u0438\u043c\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0431\u044b\u043b\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a (OpenGL, DirectX, macOS Metal Render \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0435), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043f\u043e \u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0438 \u0438\u043c\u0435\u044e\u0442 \u043d\u0435\u043e\u0434\u043d\u043e\u0440\u043e\u0434\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0431\u044b\u043b \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0432 \u0441\u0438\u043b\u0443 \u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 (\u043e\u043d \u0437\u0430\u043d\u044f\u043b \u0431\u044b \u0432\u0441\u044e \u0441\u0442\u0430\u0442\u044c\u044e). \u0412\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u0434\u0430 \u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u043d\u0443\u044e \u0438 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0443\u044e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u044d\u0442\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/4h\/zl\/s8\/4hzls8dhstsedrdmuwzoagtifho.png\" data-src=\"https:\/\/habrastorage.org\/webt\/4h\/zl\/s8\/4hzls8dhstsedrdmuwzoagtifho.png\"\/><\/p>\n<p>  \u0411\u0435\u0433\u043b\u043e\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043d\u0430 \u043d\u0435\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0441\u0447\u0443\u0440 \u0441\u043b\u043e\u0436\u043d\u044b\u043c. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438, \u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e \u0432\u0441\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u0438 \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0430\u043a\u0438\u043c \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0434\u0435\u043b\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u0431\u044b \u0432\u0441\u0435 \u0445\u0443\u0436\u0435. \u042d\u0442\u043e \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u0442\u043e \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.\u00a0<\/p>\n<p>  \u042f \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043d\u0430\u0434 \u0442\u0435\u043c, \u0430 \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432 \u0438\u0442\u043e\u0433\u0435? \u041a\u0430\u043a\u0438\u043c \u0431\u044b \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442? \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 (\u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442) \u2014 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <i>f(x)<\/i>:\u00a0<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/2q\/km\/de\/2qkmde4wqkz80x4ois6eqn-zp5q.png\" data-src=\"https:\/\/habrastorage.org\/webt\/2q\/km\/de\/2qkmde4wqkz80x4ois6eqn-zp5q.png\"\/><\/p>\n<p>  \u041d\u0430 \u044d\u0442\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435, \u0442\u043e \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0435\u0431\u0435 \u044d\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c: \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 (\u0444\u0443\u043d\u043a\u0446\u0438\u0438), \u0435\u0441\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b (\u043e\u0431\u044a\u0435\u043a\u0442\u044b) \u2014 \u0438 \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043d\u0435\u043a\u0430\u044f \u00ab\u0447\u0435\u0440\u043d\u0430\u044f \u043c\u0430\u0433\u0438\u044f\u00bb, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c.<\/p>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u0442\u0443 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443, \u043c\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u0448\u043b\u0438 \u0432\u043e\u0442 \u043a \u0442\u0430\u043a\u043e\u0439 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/u_\/ut\/-d\/u_ut-dlgclwudr_oz1v2iv3yjzc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/u_\/ut\/-d\/u_ut-dlgclwudr_oz1v2iv3yjzc.png\"\/><\/p>\n<p>  \u041d\u0438\u0436\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a\u0430\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u00ab\u043c\u0430\u0433\u0438\u044f\u00bb \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0421++ \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043a\u0430\u043a\u0438\u0435 \u0435\u0449\u0435 \u043f\u043b\u044e\u0441\u044b \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435.<\/p>\n<h2>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/h2>\n<p>  \u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0447\u0430\u0441\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0430 C++ \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c\u043e\u043c. \u041e\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c\u0438 \u0434\u043e\u0441\u0442\u043e\u0438\u043d\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430\u043c\u0438. \u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 std::variant, \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <a href=\"https:\/\/www.youtube.com\/watch?v=gKbORJtnVu8\">\u00ab\u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f\u00bb<\/a> \u0438 <a href=\"https:\/\/www.youtube.com\/watch?v=PEcy1vYHb8A\">\u00ab\u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c\u00bb<\/a>.\u00a0<\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432 \u043a\u043e\u0434\u0435 \u2014 \u0444\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0443 \u0438 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u044e \u0435\u0433\u043e \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0432 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e C++ \u044f \u0438 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0443\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<p>  \u0421\u043f\u0435\u0440\u0432\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0431\u043b\u0438\u0437\u043a\u0438\u0445 \u043f\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e \u0442\u0438\u043f\u043e\u0432, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d-\u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u0432\u0443\u0445\u043c\u0435\u0440\u043d\u044b\u0445 \u0444\u0438\u0433\u0443\u0440 \u0438 (\u043a\u0430\u043a \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445) \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0435\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"cpp\">struct Point { \u00a0\u00a0\u00a0\u00a0int x = 0, y = 0;  \u00a0\u00a0\u00a0\u00a0Point() = default; \u00a0\u00a0\u00a0\u00a0Point(int ax, int ay)\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: x(ax), y(ay)\u00a0 \u00a0\u00a0\u00a0\u00a0{} \u00a0\u00a0\u00a0\u00a0int area() const { return 0; } \u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0out &lt;&lt; \"point: [\" &lt;&lt; x &lt;&lt; ',' &lt;&lt; y &lt;&lt; ']' &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0} };  struct Rect { \u00a0\u00a0\u00a0\u00a0int x = 0, y = 0, w = 0, h = 0;  \u00a0\u00a0\u00a0\u00a0Rect() = default; \u00a0\u00a0\u00a0\u00a0Rect(int ax, int ay, int aw, int ah) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: x(ax), y(ay), w(aw), h(ah) \u00a0\u00a0\u00a0\u00a0{} \u00a0\u00a0\u00a0\u00a0int area() const { return w * h; } \u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0out &lt;&lt; \"rect: [\" &lt;&lt; x &lt;&lt; ',' &lt;&lt; y &lt;&lt; \" (\" &lt;&lt; w &lt;&lt; 'x' &lt;&lt; h &lt;&lt; \")]\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0} };  struct Line { \u00a0\u00a0\u00a0\u00a0\u00a0int x1 = 0, x2 = 0, y1 = 0, y2 = 0; \u00a0\u00a0\u00a0\u00a0\u00a0Line() = default; \u00a0\u00a0\u00a0\u00a0\u00a0Line(int ax1, int ay1, int ax2, int ay2) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: x1(ax1), x2(ax2), y1(ay1), y2(ay2) \u00a0\u00a0\u00a0\u00a0\u00a0{} \u00a0\u00a0\u00a0\u00a0\u00a0int area() const { return 0; } \u00a0\u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0out &lt;&lt; \"line: [(\" &lt;&lt; x1 &lt;&lt; ',' &lt;&lt; y1 &lt;&lt; \"),(\" &lt;&lt; x2 &lt;&lt; ',' &lt;&lt; y2 &lt;&lt; \")]\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0\u00a0} };   int main() { \u00a0\u00a0\u00a0\u00a0using Shape = std::variant&lt;Point, Rect, Line>;  \u00a0\u00a0\u00a0\u00a0std::vector&lt;Shape> shapes; \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Point{ 10, 10 }); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Rect{ -5, 5, 10, 10 }); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Line{ 1, 1, 4, 5 }); \u00a0\u00a0\u00a0\u00a0for (const auto&amp; shape : shapes) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::visit(shape, [](const auto&amp; s) { s.draw(std::cout); }); } <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0442\u043e \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"cpp\"> point: [10,10] rect: [-5,5 (10x10)] line: [(1,1),(4,5)] <\/code><\/pre>\n<p>  \u041c\u043d\u043e\u0433\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0437\u0434\u0435\u0441\u044c \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u043f\u043e\u0434\u0432\u043e\u0434\u044f \u0438\u0442\u043e\u0433\u0438 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0438 \u0442. \u043f. \u041d\u043e \u043c\u044b \u043f\u043e\u0439\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.\u00a0<\/p>\n<p>  \u0427\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435? \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0438 \u043d\u0430\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e? \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043d\u0435\u0442, \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447\u0430\u0445 \u043d\u0430\u0434\u043e \u0443\u043c\u0435\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u0439: \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u0435\u0442\u0438 \/ \u0444\u0430\u0439\u043b\u0430 \/ \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442. \u0434. \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441: \u0430 \u043a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0442 \u0441\u0430\u043c\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430?<\/p>\n<h2>\u0424\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434<\/h2>\n<p>  \u0422\u0443\u0442 \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u0438\u0439\u0442\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u00ab\u0444\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434\u00bb. \u0412\u0441\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043c\u043d\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e \u043c\u044b \u0438\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c. \u0422\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443: \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0444\u0430\u0431\u0440\u0438\u043a\u0430 \u0434\u043b\u044f std::variant.<br \/>  \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0449\u0435:<\/p>\n<pre><code class=\"cpp\">enum ShapeType { \u00a0\u00a0\u00a0\u00a0ST_Point, \u00a0\u00a0\u00a0\u00a0ST_Rect, \u00a0\u00a0\u00a0\u00a0ST_Line };   Shape createShape(ShapeType type) { \u00a0\u00a0\u00a0\u00a0switch(type) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0case ST_Point: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Point{}; \u00a0\u00a0\u00a0\u00a0case ST_Rect: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Rect{}; \u00a0\u00a0\u00a0\u00a0case ST_Line: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Line{}; \u00a0\u00a0\u00a0\u00a0\/\/ ... \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\/\/ ??? } <\/code><\/pre>\n<p>  \u041d\u043e \u0442\u0443\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c. \u0427\u0442\u043e, \u0435\u0441\u043b\u0438 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0442 \u0442\u0438\u043f\u0430? \u0427\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043d\u043e \u0438 \u0434\u0440\u0443\u0433\u0438\u0435? \u041a\u0430\u0436\u0434\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0430 \u0442\u0438\u043f\u043e\u0432 \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 Enum + \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Case \u0432 Switch \u2014 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e.<\/p>\n<p>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u0438 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0442\u0438\u043f \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c std::variant::monostate \u0438\u043b\u0438 std::optional. \u041a\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0443\u0442\u0435\u043c \u043f\u043e\u0439\u0442\u0438 \u2014 \u0434\u0435\u043b\u043e \u0432\u043a\u0443\u0441\u0430. \u0414\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u044f \u0432\u044b\u0431\u0440\u0430\u043b std::optional. \u0422\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u0442\u0438\u043f\u0430 Shape:<\/p>\n<pre><code class=\"cpp\">using Shape = std::optional&lt; std::variant&lt;Point, Rect, Line> >; <\/code><\/pre>\n<p>  \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0443\u0436\u0435 \u0436\u0443\u0442\u043a\u043e\u0432\u0430\u0442\u043e. \u0418\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u0430 \u0442\u0438\u043f\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u00ab\u0444\u0430\u0441\u0430\u0434\u00bb \u0438 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u043d\u0438\u043c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"cpp\">class Shape { public: \u00a0\u00a0\u00a0\u00a0using Data = std::variant&lt;Point, Rect, Line>;  \u00a0\u00a0\u00a0\u00a0Shape() = default;  \u00a0\u00a0\u00a0\u00a0template&lt;class T> \u00a0\u00a0\u00a0\u00a0explicit Shape(T shape) : d(std::move(shape)) {}  \u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"error: shape was not set to an instance of an object\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::visit([&amp;out](const auto&amp; s) { s.draw(out); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0int area() const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return 0; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return std::visit([](const auto&amp; s) { return s.area(); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0explicit operator bool() const { return !!d; }  private: \u00a0\u00a0\u00a0\u00a0std::optional&lt;Data> d; };   int main() { \u00a0\u00a0\u00a0\u00a0\u00a0std::vector&lt;Shape> shapes; \u00a0\u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Point{ 10, 10 }); \u00a0\u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Rect{ -5, 5, 10, 10 }); \u00a0\u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Line{ 1, 1, 4, 5 }); \u00a0\u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Shape{}); \u00a0\u00a0\u00a0\u00a0\u00a0for (const auto&amp; shape : shapes) \u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (shape) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0shape.draw(std::cout); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"unable to draw shape\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0\u00a0} } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442 Shape \u043e\u0431\u0440\u0435\u043b Value-semantic \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u0441\u0442\u0430\u043b Nullable-\u0442\u0438\u043f\u043e\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0442\u044c Shape \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430.\u00a0<\/p>\n<h2>\u041c\u043e\u0441\u0442 \u043c\u0435\u0436\u0434\u0443 \u043c\u0438\u0440\u0430\u043c\u0438 Compile-time \u0438 Run-time<\/h2>\n<p>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u043e\u0442\u044f \u0431\u044b \u0438\u043c\u0435\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"cpp\">template&lt;class _Variant, class... _Args> std::variant&lt;_Types...> createVariant(int i, _Args&amp;&amp;... args) { \u00a0\u00a0\u00a0\u00a0return std::variant&lt;_Types...>(std::in_place_index&lt;i>(), std::forward&lt;_Args>(args)...); } <\/code><\/pre>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0441 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442, \u043d\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0441 std::variant, \u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u043d\u0430 Compile-time-\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, \u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u0432 Run-time. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u00ab\u043c\u043e\u0441\u0442\u0438\u043a\u00bb \u043c\u0435\u0436\u0434\u0443 Compile-time \u0438 Run-time.<\/p>\n<p>  \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Boost, \u043d\u043e \u044d\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u0437\u043b\u0438\u0448\u043d\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c, \u0435\u0441\u043b\u0438 \u043e\u0442 \u043d\u0435\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 std::variant, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 Boost \u2014 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430.<\/p>\n<p>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e STL \u0438 \u0441\u0430\u043c \u044f\u0437\u044b\u043a C++. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u043e Run-time-\u0438\u043d\u0434\u0435\u043a\u0441\u0443 Compile-time-\u0438\u043d\u0434\u0435\u043a\u0441 \u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 std::in_place_index:<\/p>\n<pre><code class=\"cpp\">template &lt;class _Variant, std::size_t I = 0> _Variant createVariant(std::size_t index)\u00a0 { \u00a0\u00a0\u00a0\u00a0if constexpr(I >= std::variant_size_v&lt;_Variant>) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw std::runtime_error{\"index \" + std::to_string(I + index) + \" out of bounds\"}; \u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return index == 0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0? _Variant{std::in_place_index&lt;I>} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: createVariant&lt;_Variant, I + 1>(index - 1); } <\/code><\/pre>\n<p>  \u0418 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0443\u0436\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u043b\u043e\u0441\u044c, \u0445\u043e\u0442\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u0447\u0435\u0440\u043d\u0430\u044f \u043c\u0430\u0433\u0438\u044f.<\/p>\n<p>  \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u041f\u0435\u0440\u0432\u0430\u044f \u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u2014 \u043c\u044b \u043d\u0435 \u0432\u044b\u0448\u043b\u0438 \u0437\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 std::variant \u0442\u0438\u043f\u043e\u0432. \u042d\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u0430 Constexpr, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u0432 Compile-time. \u0412 \u0432\u0435\u0442\u043a\u0435 Else \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435: \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e, \u0442\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c I \u0432 std::in_place_index \u043a\u0430\u043a \u043d\u0435\u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u2014 \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f? \u0414\u0430, \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a. \u042d\u0442\u043e\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 Compile-time-\u0438\u043d\u0434\u0435\u043a\u0441. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"cpp\">using Shapes = std::variant&lt;Point, Rect, Line>; auto result = createVariant&lt;Shapes>(2); <\/code><\/pre>\n<p>  \u0418 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u0438\u043c \u043d\u0430 \u043d\u0435\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u0438 \u0432\u043e \u0447\u0442\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u044b:<\/p>\n<pre><code class=\"cpp\">createVariant&lt;Shapes, I=0>(2): index = 2; index -1, I + 1 \u2192 createVariant&lt;Shapes, I=1>(1): index = 1; \u2192 index \u2013 1, I + 1 \u2192 createVariant&lt;Shapes, I=2>(0): index = 0 \u2192 return Shapes{std::in_place_index&lt;2>}; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0442\u0430 \u043c\u0430\u0433\u0438\u044f: Compile-time-\u0438\u043d\u0434\u0435\u043a\u0441 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u0435\u0442, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a Run-time-\u0438\u043d\u0434\u0435\u043a\u0441 \u0443\u0431\u044b\u0432\u0430\u0435\u0442. \u041a\u043e\u0433\u0434\u0430 Run-time-\u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u0430\u043d\u0435\u0442 \u0440\u0430\u0432\u043d\u044b\u043c \u043d\u0443\u043b\u044e, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u0432 \u043d\u0443\u0436\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u043d\u0443\u0436\u043d\u044b\u043c Compile-time-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 std::in_place_index. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0430\u043a-\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u0438 \u043d\u0443\u0436\u043d\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430.<\/p>\n<blockquote><p>\u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0434\u0430\u0441\u0442\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c: \u0430 \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438? \u0414\u0430, \u043c\u043e\u0436\u0435\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e: \u0440\u0430\u0441\u043f\u043b\u0430\u0442\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 Code Bloat \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0430\u0446\u0438\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 Compile-time-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e std::variant.<\/p><\/blockquote>\n<p>  \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u0440\u044e\u043a\u0438 \u0441 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430\u043c\u0438, std::make_index_sequence \u0438 fold expressions \u0438\u0437 C++17:<\/p>\n<pre><code class=\"cpp\">template&lt;class _Variant> struct variant_creator \/\/ \u0430\u043d\u0430\u043b\u043e\u0433 std::array, \u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 { \u00a0\u00a0\u00a0\u00a0\/\/ \u0447\u0438\u0441\u043b\u043e \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 std::variant&lt;...> \u00a0\u00a0\u00a0\u00a0static constexpr size_t N = std::variant_size_v&lt;_Variant>; \u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\/\/ \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u00a0\u00a0\u00a0\u00a0typedef _Variant(*creator)();\u00a0 \u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e: \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ \u0441 index_sequence&lt;I...> \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c I... \u0432 fold expression \u00a0\u00a0\u00a0\u00a0variant_creator() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: variant_creator(std::make_index_sequence&lt;N>{}) \u00a0\u00a0\u00a0\u00a0{}  \u00a0\u00a0\u00a0\u00a0_Variant operator()(size_t i) const\u00a0 \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (i >= N) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw std::runtime_error(\"invalid index\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return arr[i](); \u00a0\u00a0\u00a0\u00a0} private: \u00a0\u00a0\u00a0\u00a0template&lt;size_t... I> \u00a0\u00a0\u00a0\u00a0variant_creator(std::index_sequence&lt;I...>) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: arr{ &amp;create&lt;I>... } \/\/ \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f fold expression \u00a0\u00a0\u00a0\u00a0{}  \u00a0\u00a0\u00a0\u00a0template&lt;size_t I> \u00a0\u00a0\u00a0\u00a0static _Variant create() { return _Variant{std::in_place_index&lt;I>}; } \u00a0\u00a0\u00a0\u00a0 private: \u00a0\u00a0\u00a0\u00a0creator lookup[N] = { nullptr }; \/\/ \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 };  template &lt;class _Variant, std::size_t I = 0> _Variant createVariant(std::size_t index)\u00a0 { \u00a0\u00a0\u00a0\u00a0static variant_creator&lt;_Variant> creator; \u00a0\u00a0\u00a0\u00a0return creator(index); } <\/code><\/pre>\n<p>  \u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 std::variant. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 \u043d\u0430\u0448\u0438 \u043d\u0443\u0436\u0434\u044b, \u043d\u0435 \u0442\u0435\u0440\u044f\u044f \u043e\u0431\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"cpp\">template&lt;class... _Types> struct VariantFactory { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kTypeCount = sizeof...(_Types); \u00a0\u00a0\u00a0\u00a0using VariantType = std::variant&lt;_Types...>; \u00a0\u00a0\u00a0\u00a0using ResultType = std::optional&lt;VariantType>;  \u00a0\u00a0\u00a0\u00a0bool emplace(ResultType&amp; result, int type) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant(result, type); \u00a0\u00a0\u00a0\u00a0}  protected: \u00a0\u00a0\u00a0\u00a0template &lt;std::size_t I = 0> \u00a0\u00a0\u00a0\u00a0static bool emplaceVariant(ResultType&amp; result, std::size_t index) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if constexpr (I >= kTypeCount) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (index == 0) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result.emplace(std::in_place_index&lt;I>); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant&lt;I + 1>(result, index - 1); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0} }; <\/code><\/pre>\n<p>  \u041c\u044b \u043e\u0431\u0435\u0440\u043d\u0443\u043b\u0438 \u043d\u0430\u0448\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 VariantFactory. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c std::optional, \u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0443\u0434\u0430\u0447\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c False, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0441\u043c\u043e\u0433 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u0443 \u0444\u0430\u0431\u0440\u0438\u043a\u0443 \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">#include \"VariantFactory.h\"  class Shape { public: \u00a0\u00a0\u00a0\u00a0using ShapeFactory = VariantFactory&lt;Point, Rect, Line>;  \u00a0\u00a0\u00a0\u00a0enum ShapeType \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Invalid = -1, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Point, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Rect, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Line \u00a0\u00a0\u00a0\u00a0};  \u00a0\u00a0\u00a0\u00a0Shape(int key = ST_Invalid) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (key != ST_Invalid &amp;&amp; !ShapeFactory{}.emplace(d, key)) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"error: unable to create shape for key \" &lt;&lt; key &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"error: shape was not set to an instance of an object\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::visit([&amp;out](const auto&amp; s) { s.draw(out); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0int area() const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return 0; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return std::visit([](const auto&amp; s) { return s.area(); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0explicit operator bool() const { return !!d; }  private: \u00a0\u00a0\u00a0\u00a0ShapeFactory::ResultType d; };   int main() { \u00a0\u00a0\u00a0\u00a0std::vector&lt;Shape> shapes; \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Point); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Rect); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Line); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Shape{}); \u00a0\u00a0\u00a0\u00a0for (const auto&amp; shape : shapes) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (shape) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0shape.draw(std::cout); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"unable to draw shape\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0} } <\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0442\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0435\u0449\u0435 \u043d\u0430 \u043e\u0434\u043d\u0443 \u0434\u0435\u0442\u0430\u043b\u044c: \u043d\u0430\u0448\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f VariantFactory \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0442\u0438\u043f\u044b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435\u0441\u044f \u0432 std::variant, \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e? \u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u044d\u0442\u0438 \u0442\u0438\u043f\u044b \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435? \u041a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 (<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack\">variadic template argument pack<\/a>)?<\/p>\n<h2>\u041e\u0431\u043e\u0431\u0449\u0430\u0439 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0439<\/h2>\n<p>  \u0420\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u043d\u0430\u0448\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430 \u044d\u0442\u0438 \u0441\u043b\u0443\u0447\u0430\u0438: \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0435\u0442\u0430 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0422\u0435\u043a\u0443\u0449\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e \u0443\u0436\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u043c\u0443 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u043d\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">template &lt;std::size_t I = 0, class... _Args> static constexpr bool emplaceVariant(ResultType&amp; result, std::size_t index, _Args&amp;&amp;... args) { \u00a0\u00a0\u00a0\u00a0if constexpr (I >= kTypeCount) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (index == 0) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result.emplace(std::in_place_index&lt;I>, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant&lt;I + 1>(result, index - 1, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0} } <\/code><\/pre>\n<p>  \u041d\u043e, \u0443\u0432\u044b, \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432\u044b\u0434\u0430\u0441\u0442 \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443: \u00ab\u041d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438\u00bb. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0435, \u0442\u043e \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u043a\u043e\u0434 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u0442\u0430\u043a, \u0447\u0442\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e! \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0442\u0430\u043a \u0438\u0437-\u0437\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 C++. \u0412 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432 \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c, \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0441\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0438\u043f \u0438\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 _Args\u2026 \u0438\u043b\u0438 \u043d\u0435\u0442. \u0418 \u043a\u0430\u043a \u043d\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 STL \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u2014 std::<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/is_constructible\">is_constructible<\/a>&lt;_Args&#8230;>. \u0412\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"cpp\">template&lt;size_t I> using AlternativeType = std::variant_alternative_t&lt;I, VariantType>;  template &lt;std::size_t I = 0, class... _Args> static constexpr bool emplaceVariant(ResultType&amp; result, std::size_t index, _Args&amp;&amp;... args) { \u00a0\u00a0\u00a0\u00a0if constexpr (I >= kTypeCount) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (index == 0) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if constexpr (std::is_constructible&lt;AlternativeType&lt;I>, _Args...>{}) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result.emplace(std::in_place_index&lt;I>, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant&lt;I + 1>(result, index - 1, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0} } <\/code><\/pre>\n<p>  \u041f\u043e\u043f\u0440\u0430\u0432\u0438\u043c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 Shape, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cpp\">#include \"VariantFactory.h\"  class Shape { public: \u00a0\u00a0\u00a0\u00a0using ShapeFactory = VariantFactory&lt;Point, Rect, Line>;  \u00a0\u00a0\u00a0\u00a0enum ShapeType \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Invalid = -1, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Point, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Rect, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ST_Line \u00a0\u00a0\u00a0\u00a0};  \u00a0\u00a0\u00a0\u00a0explicit Shape(int key = ST_Invalid) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: Shape(key) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0template&lt;class... _Args> \u00a0\u00a0\u00a0\u00a0Shape(int key, _Args&amp;&amp;... args) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (key != ST_Invalid &amp;&amp; !ShapeFactory{}.emplace(d, key, std::forward&lt;_Args_>(args)...)) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"error: unable to create shape for key \" &lt;&lt; key &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0void draw(std::ostream&amp; out) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"error: shape was not set to an instance of an object\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::visit([&amp;out](const auto&amp; s) { s.draw(out); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0int area() const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!d) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return 0; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return std::visit([](const auto&amp; s) { return s.area(); }, *d); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0explicit operator bool() const { return !!d; }  private: \u00a0\u00a0\u00a0\u00a0ShapeFactory::ResultType d; };   int main() { \u00a0\u00a0\u00a0\u00a0std::vector&lt;Shape> shapes; \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Point, 10, 10); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Rect, -5, -5, 10, 10); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(ST_Line, 1, 1, 4, 5); \u00a0\u00a0\u00a0\u00a0shapes.emplace_back(Shape{}); \u00a0\u00a0\u00a0\u00a0for (const auto&amp; shape : shapes) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (shape) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0shape.draw(std::cout); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::cerr &lt;&lt; \"unable to draw shape\" &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\/\/ Output: \u00a0\u00a0\u00a0\u00a0\/\/ point: [10,10] \u00a0\u00a0\u00a0\u00a0\/\/ rect: [-5,5 (10x10)] \u00a0\u00a0\u00a0\u00a0\/\/ line: [(1,1),(4,5)] \u00a0\u00a0\u00a0\u00a0\/\/ unable to draw shape } <\/code><\/pre>\n<p>  \u0417\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u043b\u043e\u0441\u044c!<\/p>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443, \u043d\u043e \u043c\u044b \u043f\u043e\u0439\u0434\u0435\u043c \u0435\u0449\u0435 \u0434\u0430\u043b\u044c\u0448\u0435. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0440\u044f\u0434\u043e\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0442\u0438\u043f\u044b \u0432 \u043d\u0430\u0448\u0435\u0439 \u0444\u0430\u0431\u0440\u0438\u043a\u0435, \u0432 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043b \u0441 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0442\u0438\u043f\u044b \u0432 Enum ShapeType. \u0412 \u043d\u0430\u0448\u0435\u043c \u0438\u0433\u0440\u0443\u0448\u0435\u0447\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0440\u0443\u0434\u0430. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0436\u0435 \u043a\u043e\u0434 \u043f\u0438\u0448\u0443\u0442 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439, \u0438 \u0443\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u044d\u0442\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0425\u043e\u0440\u043e\u0448\u0435\u0439 \u0438\u0434\u0435\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043d\u0435\u043a\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043f\u043e\u0438\u0441\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u0432\u043d\u0443\u0442\u0440\u0438 std::variant:<\/p>\n<pre><code class=\"css\">template&lt;class... _Types> struct VariantFactory { \u00a0\u00a0\u00a0\u00a0using VariantType = std::variant&lt;_Types...>; \u00a0\u00a0\u00a0\u00a0using ResultType = std::optional&lt;VariantType>;  \u00a0\u00a0\u00a0\u00a0static constexpr size_t kTypeCount = sizeof...(_Types); \u00a0\u00a0\u00a0\u00a0static constexpr size_t kLookup[kTypeCount] = { ??? };  \u00a0\u00a0\u00a0\u00a0template&lt;class... _Args> \u00a0\u00a0\u00a0\u00a0bool emplace(ResultType&amp; result, int type, _Args&amp;&amp;... args) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto first = std::begin(kLookup); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto last = std::end(kLookup); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto it = std::find(first, last, type); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (it == last) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant(result, std::distance(first, it), std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0\/\/ as before \u00a0\u00a0\u00a0\u00a0\/\/ ... }; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0437\u0430\u0434\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. \u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c: \u043f\u0443\u0441\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f \u0441\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0441\u0435\u0431\u0435 \u0441\u0432\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0442\u0438\u043f\u0430 \u0432 Compile-time, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct Point { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kElementType = Shape::ST_Point; \u00a0\u00a0\u00a0\u00a0\/\/ as before \u00a0\u00a0\u00a0\u00a0\/\/ ... };  struct Rect { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kElementType = Shape::ST_Rect; \u00a0\u00a0\u00a0\u00a0\/\/ as before \u00a0\u00a0\u00a0\u00a0\/\/ ... };  struct Line { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kElementType = Shape::ST_Line; \u00a0\u00a0\u00a0\u00a0\/\/ as before \u00a0\u00a0\u00a0\u00a0\/\/ ... }; <\/code><\/pre>\n<p>  \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 kLookup \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438:<\/p>\n<pre><code class=\"cpp\">template&lt;class... _Types> struct VariantFactory { \u00a0\u00a0\u00a0static constexpr size_t kTypeCount = sizeof...(_Types); \u00a0\u00a0\u00a0static constexpr size_t kLookup[kTypeCount] = { _Types::kElementType... }; \/\/ as before ... }; <\/code><\/pre>\n<p>  \u041f\u0440\u0430\u0432\u0434\u0430, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0442\u0435\u043c, \u0447\u0442\u043e \u0442\u0438\u043f \u043e\u0431\u044f\u0437\u0430\u043d \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c. \u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f, \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u0430\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430:<\/p>\n<pre><code class=\"css\">template&lt;size_t _ElemId> struct ShapeAdapter { \u00a0\u00a0\u00a0\u00a0static constexpr kElementType = _ElemId; };  struct Point : public ShapeAdapter&lt;Shape::ST_Point> { \u00a0\u00a0\u00a0\u00a0\/\/ as before... }; <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c VariantFactory \u0431\u043e\u043b\u0435\u0435 \u0448\u0438\u0440\u043e\u043a\u043e, \u0442\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0435\u043c\u0441\u044f \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u2014 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f \u0438\u043c\u0435\u043b \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 kElementType, \u0430 \u043d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u043c\u0435\u0442\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043e\u0431\u0449\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0427\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u044d\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0431\u0435\u0433\u043d\u0443\u0442\u044c \u043a \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u043c\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043e\u0442 VariantFactory&lt;_Types\u2026> \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b-\u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"css\">template&lt;class... _Types> struct VariantFactory { \u00a0\u00a0\u00a0\u00a0using VariantType = std::variant&lt;_Types...>; \u00a0\u00a0\u00a0\u00a0using ResultType = std::optional&lt;VariantType>; \u00a0\u00a0\u00a0\u00a0static constexpr size_t kTypeCount = sizeof...(_Types);  protected: \u00a0\u00a0\u00a0\u00a0template&lt;class... _Args> \u00a0\u00a0\u00a0\u00a0bool emplace(ResultType&amp; result, int type, _Args&amp;&amp;... args) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return createVariant(result, type, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0bool emplace(ResultType&amp; result, int type, int (&amp;lookup)[kTypeCount], _Args&amp;&amp;... args) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto first = std::begin(lookup); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto last = std::end(lookup); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0auto it = std::find(first, last, type); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (it == last) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant(result, std::distance(first, it), std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0}  private: \u00a0\u00a0\u00a0\u00a0template &lt;std::size_t I = 0, class... _Args> \u00a0\u00a0\u00a0\u00a0static bool emplaceVariant(ResultType&amp; result, std::size_t index, _Args&amp;&amp;... args) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ as before... \u00a0\u00a0\u00a0\u00a0} }; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">template&lt;class... _Types> struct ShapeFactory : public VariantFactory&lt;_Types...> { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kLookup[] = { _Types::kElementType... };  \u00a0 \u00a0 bool createShape(ResultType&amp; result, int type) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this->emplace(result, type, kLookup); \u00a0\u00a0\u00a0\u00a0} }; <\/code><\/pre>\n<p>  \u042d\u0442\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0435, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u043d\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0438 \u043c\u0435\u0442\u0430\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0442 VariantFactory. \u041c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u043f\u043e\u0439\u0442\u0438 \u0435\u0449\u0435 \u0434\u0430\u043b\u044c\u0448\u0435? \u041e\u0442\u0432\u0435\u0442 \u2014 \u0434\u0430!<\/p>\n<h2>\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 \u043a\u0430\u043a \u043a\u043b\u044e\u0447\u0438 \u0432 \u0444\u0430\u0431\u0440\u0438\u043a\u0435<\/h2>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0448 \u0448\u0430\u0433 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0432\u0441\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0438 \u0440\u0443\u0447\u043d\u043e\u0439 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Enum. \u0418\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u0432 Compile-time. \u0412 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u0441\u043c\u044b\u0441\u043b\u0435 \u044d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 RTTI (Run-Time Type Information), \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e CTTI (Compile-Time Type Information). \u0421\u0440\u0430\u0437\u0443 \u043e\u0433\u043e\u0432\u043e\u0440\u044e\u0441\u044c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u0438\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u2014 \u043e\u0431\u0448\u0438\u0440\u043d\u0430\u044f \u0442\u0435\u043c\u0430, \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u0430\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u043f\u043e\u0434 \u0441\u0430\u043c\u044b\u0435 \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f. \u0422\u0443\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u0430\u0439\u0434\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0432\u043e\u0439 \u0432\u043a\u0443\u0441 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0445 \u0442\u0440\u044e\u043a\u043e\u0432 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"cpp\">template&lt;typename T> struct type { static constexpr char _dummy_ = 0; };  template&lt;typename T> inline constexpr const void* kUniqueId = &amp;type&lt;T>::_dummy_;  template&lt;typename T> static size_t unique_id() { return reinterpret_cast&lt;size_t>(kUniqueId&lt;T>); }  int main() { \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"kUniqueId&lt;int>=\" &lt;&lt; (void*)kUniqueId&lt;int> &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"kUniqueId&lt;double>=\" &lt;&lt; (void*)kUniqueId&lt;double> &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"kUniqueId&lt;std::string>=\" &lt;&lt; (void*)kUniqueId&lt;std::string> &lt;&lt; std::endl;  \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"unique_id&lt;int>()=\" &lt;&lt; (void*)kUniqueId&lt;int> &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"unique_id&lt;double>()=\" &lt;&lt; (void*)kUniqueId&lt;double> &lt;&lt; std::endl; \u00a0\u00a0\u00a0\u00a0std::cout &lt;&lt; \"unique_id&lt;std::string>()=\" &lt;&lt; (void*)kUniqueId&lt;std::string> &lt;&lt; std::endl;  \u00a0\u00a0\u00a0\u00a0\/\/ Possible output: \u00a0\u00a0\u00a0\u00a0\/\/ kUniqueId&lt;int>=0x4019d8 \u00a0\u00a0\u00a0\u00a0\/\/ kUniqueId&lt;double>=0x4019d7 \u00a0\u00a0\u00a0\u00a0\/\/ kUniqueId&lt;std::string>=0x4019d6 \u00a0\u00a0\u00a0\u00a0\/\/ unique_id&lt;int>()=0x4019d8 \u00a0\u00a0\u00a0\u00a0\/\/ unique_id&lt;double>()=0x4019d7 \u00a0\u00a0\u00a0\u00a0\/\/ unique_id&lt;std::string>()=0x4019d6 } <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f kUniqueId \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c Const Void* \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u0438 \u043d\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0438\u0445 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0442\u0438\u043f, \u0445\u043e\u0442\u044f \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0438\u0447\u0435\u043c\u0443 \u043d\u0435 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0440\u0435\u0447\u0438\u0442. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0431\u044b\u043b\u0430 \u0432 Run-time-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u0442\u043e \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0443\u0431\u0440\u0430\u0442\u044c constexpr, \u0442\u043e \u043b\u0438\u0448\u0438\u043c\u0441\u044f Compile-time. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f Run-time-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e unique_id(), \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0443\u044e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u0441\u0435 \u0442\u043e\u0433\u043e \u0436\u0435 kUniqueId.<\/p>\n<p>  \u0415\u0441\u0442\u044c \u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438. \u041a \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\u0430\u0434\u0440\u0435\u0441 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438 \u0441\u0430\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043e\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043a \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438;  <\/li>\n<li>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u0433\u0440\u0430\u043d\u0438\u0446 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0438 \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u0435\u0435 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.  <\/li>\n<\/ul>\n<p>  \u042d\u0442\u043e \u043d\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435: \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0441\u0447\u0435\u0440\u043f\u044b\u0432\u0430\u044e\u0449\u0438\u043c\u0438. \u0412\u044b\u0431\u043e\u0440 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u043f\u0440\u0438\u0432\u0435\u043b \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0433\u043b\u0443\u0431\u0436\u0435 \u0438 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.<\/p>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432\u0441\u0435 \u044d\u0442\u0438 \u0437\u043d\u0430\u043d\u0438\u044f, \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e, \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043e\u0431\u0449\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e VariantFactory:<\/p>\n<pre><code class=\"css\">#include \"unique_id.h\"  template&lt;class... _Types> struct VariantFactory { \u00a0\u00a0\u00a0\u00a0static constexpr size_t kTypeCount = sizeof...(_Types); \u00a0\u00a0\u00a0\u00a0static constexpr const void* kLookup[] = { kUniqueId&lt;_Types>... };  \u00a0\u00a0\u00a0\u00a0using VariantType = std::variant&lt;_Types...>; \u00a0\u00a0\u00a0\u00a0using ResultType = std::optional&lt;VariantType>;  \u00a0\u00a0\u00a0\u00a0template&lt;size_t I> \u00a0\u00a0\u00a0\u00a0using AlternativeType = std::variant_alternative_t&lt;I, VariantType>;  \u00a0\u00a0\u00a0\u00a0template&lt;class... _Args> \u00a0\u00a0\u00a0\u00a0bool operator()(ResultType&amp; result, size_t type, _Args&amp;&amp;... args) const \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for (size_t i = 0; i &lt; kTypeCount; ++i) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (reinterpret_cast&lt;size_t>(kLookup[i]) == type) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant(result, I, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0}  protected: \u00a0\u00a0\u00a0\u00a0template &lt;std::size_t I = 0, class... _Args> \u00a0\u00a0\u00a0\u00a0static constexpr bool emplaceVariant(ResultType&amp; result, std::size_t index, _Args&amp;&amp;... args) \u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if constexpr (I >= kTypeCount) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (index == 0) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if constexpr (std::is_constructible&lt;AlternativeType&lt;I>, _Args...>{}) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result.emplace(std::in_place_index&lt;I>, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return emplaceVariant&lt;I + 1>(result, index - 1, std::forward&lt;_Args>(args)...); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0} }; <\/code><\/pre>\n<p>  \u0422\u0430\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0430\u044f, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u0432 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 std::variant, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h2>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u043e\u0438\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0432 \u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0440\u0430\u0441\u0445\u043e\u0436\u0435\u0435 \u043c\u043d\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e std::variant \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0442\u0430\u043a. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432: \u0437\u0434\u0435\u0441\u044c \u0438 \u0434\u0435\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0438 \u0441\u043f\u0435\u043a\u0443\u043b\u044f\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u0438 \u043c\u043d\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u0438\u0435\u043c\u043e\u0432. \u0412 \u0438\u0442\u043e\u0433\u0435, \u0435\u0441\u043b\u0438 \u0437\u0430\u043c\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c std::variant&lt;Point, Line, Rect> \u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c\u0430, \u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041e\u0434\u043d\u0430\u043a\u043e \u0443 std::variant \u0435\u0441\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u2014 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f.\u00a0<\/p>\n<p>  \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438, \u0447\u0442\u043e, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0434\u0438\u043a\u0442\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043c\u044b \u0432\u0440\u044f\u0434 \u043b\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Raw Pointers \u0432\u0432\u0438\u0434\u0443 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u2014 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c std::unique_ptr. \u0412\u0441\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u0445\u0443\u0436\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c std::shared_ptr, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c\u0441\u044f \u0435\u0449\u0435 \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u0431\u044b\u0447\u043d\u043e \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443, \u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0440\u0430\u0437\u0443 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0438 \u0445\u0440\u0430\u043d\u0438\u043c \u0432 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435.\u00a0<\/p>\n<p>  \u0418\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u0438 \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u0443\u0442\u044c: \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0443\u0447\u0430\u0441\u0442\u043a\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u2014 \u0434\u043e\u0440\u043e\u0433\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 std::variant \u0438 \u0432\u044b\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442, \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0447\u0438\u0441\u043b\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ke\/u9\/jx\/keu9jxtd-t0nkyvqy5fuuwqqogs.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ke\/u9\/jx\/keu9jxtd-t0nkyvqy5fuuwqqogs.png\"\/><\/p>\n<p>  \u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 <a href=\"https:\/\/quick-bench.com\/q\/Lcgj5zwrmkEm3HbwRcSIX6xMdzI\">\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a<\/a> \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u0443 \u0440\u0430\u0437\u043d\u0438\u0446\u0443.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e, \u043d\u043e \u0438 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0441\u0442\u044c\u044e, \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e\u043c \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u0446\u0435\u043b\u043e\u043c. \u0423\u0434\u0430\u0447\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u2014 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439 \u0432 \u0441\u0435\u0431\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0438 \u0442\u0440\u044e\u043a\u043e\u0432 \u043d\u0430\u0440\u0430\u0432\u043d\u0435 \u0441 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c\u0438 \u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u044b\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e C++. \u041a\u0430\u043a\u043e\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c, \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0432\u0430\u043c\u0438, \u043d\u043e \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u0430\u0439\u043d\u0443 \u0447\u0435\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 C++ \u0438 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u043d\u0430\u0447\u0438\u0442, \u0446\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u0430.<\/p>\n<p>  \u0423\u0437\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434 VK Teams \u043c\u043e\u0436\u043d\u043e \u043d\u0430 \u043d\u0430\u0448\u0435\u043c <a href=\"https:\/\/biz.mail.ru\/teams\/?utm_source=habr&amp;utm_medium=refferal&amp;utm_campaign=fabrica_dlya_std\">\u0441\u0430\u0439\u0442\u0435<\/a>.<\/p>\n<h2>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043c\u0443\u0434\u0440\u043e\u0441\u0442\u0438<\/h2>\n<p>  <\/p>\n<ol>\n<li><a href=\"https:\/\/github.com\/serge-sans-paille\/frozen\">https:\/\/github.com\/serge-sans-paille\/frozen<\/a>  <\/li>\n<li><a href=\"https:\/\/github.com\/Manu343726\/ctti\">https:\/\/github.com\/Manu343726\/ctti<\/a>  <\/li>\n<li><a href=\"https:\/\/mikejsavage.co.uk\/cpp-tricks-type-id\/\">https:\/\/mikejsavage.co.uk\/cpp-tricks-type-id\/<\/a>  <\/li>\n<li><a href=\"https:\/\/codereview.stackexchange.com\/questions\/209950\/unique-compile-time-constexpr-type-id-without-rtti\">https:\/\/codereview.stackexchange.com\/questions\/209950\/unique-Compile-time-constexpr-type-id-without-rtti<\/a>  <\/li>\n<li><a href=\"https:\/\/chromium.googlesource.com\/chromium\/src\/base\/+\/4443f986771406c6973d1903687762a5088f7077\/type_id.h\">https:\/\/chromium.googlesource.com\/chromium\/src\/base\/+\/4443f986771406c6973d1903687762a5088f7077\/type_id.h<\/a>  <\/li>\n<li><a href=\"https:\/\/dev.to\/heliobatimarqui\/compile-time-type-id-with-templates-c-55c4\">https:\/\/dev.to\/heliobatimarqui\/Compile-time-type-id-with-templates-c-55c4<\/a>  <\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/810085\/\"> https:\/\/habr.com\/ru\/articles\/810085\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/vk.com\/rtrg?p=VK-RTRG-1297426-bEGLU&amp;event=habr_workspace\" style=\"display:none;\" width=\"1\"><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ov\/3i\/a0\/ov3ia0xugzrnqhniljsey55ozo8.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ov\/3i\/a0\/ov3ia0xugzrnqhniljsey55ozo8.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u0443\u043a\u0430\u0440\u043e\u0432, \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 Desktop-\u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0441 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 <a href=\"https:\/\/biz.mail.ru\/teams\/?utm_source=habr&amp;utm_medium=refferal&amp;utm_campaign=fabrica_dlya_std\">VK Teams<\/a>.\u00a0<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438, \u0433\u0434\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u043d\u0430\u0435\u0442\u0435 \u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0435\u0439 \u043b\u0430\u0432\u0438\u043d\u0435 \u043a\u043e\u0434\u0430. \u0422\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c, \u0438\u0437\u0443\u0447\u0430\u0442\u044c \u0438 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u041f\u043e\u0434\u0435\u043b\u044e\u0441\u044c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0421++, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u044c compile-time \u0438 run-time \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0432 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-374565","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/374565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=374565"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/374565\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=374565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=374565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=374565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}