{"id":288311,"date":"2018-08-21T15:55:08","date_gmt":"2018-08-21T11:55:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=288311"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=288311","title":{"rendered":"Jinja2 \u0432 \u043c\u0438\u0440\u0435 C++, \u0447\u0430\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f. \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433"},"content":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/419011\/\" class=\"post__text post__text-html js-mediator-article\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c81\/fe0\/548\/c81fe0548837b911b9569cdf49d90ca2.jpg\" alt=\"Jinja2 logo\" align=\"left\"> \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043e \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 Jinja2 \u043d\u0430 C++. \u041f\u0435\u0440\u0432\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/habr.com\/post\/416581\/\">\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430, \u0438\u043b\u0438 \u043a\u0430\u043a \u044f \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b Jinja2 \u043d\u0430 C++<\/a>. \u0412 \u043d\u0435\u0439 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432. \u0418\u043b\u0438, \u0438\u043d\u0430\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 &#171;\u0441 \u043d\u0443\u043b\u044f&#187; \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043f\u0438\u0442\u043e\u043d\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"rendering-kak-takovoy\">\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0432\u043e\u0439<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0435\u0440\u0435\u0432\u043e, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0443\u0437\u043b\u044b \u0442\u0440\u0451\u0445 \u0442\u0438\u043f\u043e\u0432: <strong>\u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442<\/strong>, <strong>\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/strong> \u0438 <strong>\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/strong>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u2014 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c\u0441\u044f, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043c\u0435\u0449\u0451\u043d \u0432 \u043f\u043e\u0442\u043e\u043a, \u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u2014 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f. \u0421 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u043d\u0433\u0430, \u043d\u0435 \u0431\u044b\u043b\u043e: \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u043e\u0439\u0442\u0438 \u0432\u0441\u0435 \u0443\u0437\u043b\u044b \u0434\u0435\u0440\u0435\u0432\u0430, \u0432\u0441\u0451 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c, \u0432\u0441\u0451 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442. \u0412\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e. \u0420\u043e\u0432\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u044e\u0442\u0441\u044f \u0434\u0432\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u044f: \u0430) \u0432\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 (string \u0438\u043b\u0438 wstring); \u0431) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b inja \u0438 Jinja2CppLight. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u043c\u043e\u0435\u0439 <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\">Jinja2Cpp<\/a> \u043e\u0431\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043d\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u043d\u043e\u044e \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0431\u043e\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0441\u0442\u0440\u043e\u043a. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0432\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u0442\u0435\u0432\u0430\u043b\u0430\u0441\u044c \u043a\u0430\u043a \u0440\u0430\u0437 \u0440\u0430\u0434\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Jinja2 \u043f\u043e\u0447\u0442\u0438 \u0432 \u043f\u043e\u043b\u043d\u043e\u043c \u043e\u0431\u044a\u0451\u043c\u0435, \u0430 \u044d\u0442\u043e, \u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u044f\u0437\u044b\u043a. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u043e\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u043a\u043e\u0432\u044b\u0440\u044f\u0442\u044c\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0441 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u043e\u043c.<\/p>\n<p>  <\/p>\n<h3 id=\"vychislenie-vyrazheniy\">\u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/h3>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/46\/i0\/0y\/46i00yfhkcaiybpae4famsictho.png\" align=\"right\"> \u0428\u0430\u0431\u043b\u043e\u043d \u043d\u0435 \u0431\u044b\u043b \u0431\u044b \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c, \u0435\u0441\u043b\u0438 \u0431\u044b \u0435\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c. \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, Jinja2 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 &#171;\u0432 \u0441\u0435\u0431\u0435&#187; \u2014 \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u0430 \u043f\u043e\u0442\u043e\u043c \u0435\u0433\u043e \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c. \u041d\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 &#171;\u0441\u043d\u0430\u0440\u0443\u0436\u0438&#187;, \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043a\u0435\u0439\u0441\u043e\u043c. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 (\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b) \u0441 \u043a\u0430\u043a\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0432\u0438\u0434\u043d\u044b \u0432 \u0442\u043e\u0447\u043a\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f. \u0418 \u0437\u0430\u0433\u0432\u043e\u0437\u0434\u043a\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 Jinja2 \u0435\u0441\u0442\u044c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 (\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438), \u043d\u043e \u0435\u0449\u0451 \u0438 \u0441 \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 &#171;\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u0438&#187;. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d:<\/p>\n<p>  <\/p>\n<pre><code>{% set param1=10 %} {{ param1 }}<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0435\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0442\u0435\u043a\u0441\u0442 <code>10<\/code><br \/>  \u0412\u0430\u0440\u0438\u0430\u043d\u0442 \u0447\u0443\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code>{% set param1=10 %} {{ param1 }} {% for param1 in range(10) %}-{{ param1 }}-{% endfor %} {{ param1 }}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0443\u0436\u0435 \u0432 <code>10-0--1--2--3--4--5--6--7--8--9-10<\/code><br \/>  \u0426\u0438\u043a\u043b \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0441\u043a\u043e\u0443\u043f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0438 \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0438\u0434\u043d\u044b \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u0441\u043a\u043e\u0443\u043f\u0430, \u043a\u0430\u043a \u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0442\u0438\u0440\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0438\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c. \u0415\u0449\u0451 \u0445\u0438\u0442\u0440\u0435\u0435 \u0441 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 extends\/block, \u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0443\u0436\u0435 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 Jinja2.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439. \u0410 \u0442\u043e\u0447\u043d\u0435\u0435, \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0432\u043e\u043e\u0431\u0449\u0435:<\/p>\n<p>  <\/p>\n<pre><code>class RenderContext { public:     RenderContext(const InternalValueMap&amp; extValues, IRendererCallback* rendererCallback);      InternalValueMap&amp; EnterScope();     void ExitScope();      auto FindValue(const std::string&amp; val, bool&amp; found) const     {         for (auto p = m_scopes.rbegin(); p != m_scopes.rend(); ++ p)         {             auto valP = p-&gt;find(val);             if (valP != p-&gt;end())             {                 found = true;                 return valP;             }         }         auto valP = m_externalScope-&gt;find(val);         if (valP != m_externalScope-&gt;end())         {             found = true;             return valP;         }          found = false;         return m_externalScope-&gt;end();     }      auto&amp; GetCurrentScope() const;     auto&amp; GetCurrentScope();     auto&amp; GetGlobalScope();     auto GetRendererCallback();     RenderContext Clone(bool includeCurrentContext) const; private:     InternalValueMap* m_currentScope;     const InternalValueMap* m_externalScope;     std::list&lt;InternalValueMap&gt; m_scopes;     IRendererCallback* m_rendererCallback; };<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/63e67774dd3fad846e50101451a92c50ce1b8441\/src\/render_context.h#L19\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, \u0441\u043f\u0438\u0441\u043e\u043a (\u0441\u0442\u0435\u043a) \u0441\u043a\u043e\u0443\u043f\u043e\u0432, \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043a\u043e\u0443\u043f \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 callback-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u041d\u043e \u043e \u043d\u0451\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432 \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0451\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0441\u0430\u043c\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445. \u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 (\u0438 \u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439) Jinja2 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 \u0442\u0438\u043f\u043e\u0432:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0427\u0438\u0441\u043b\u0430 (int, double)<\/li>\n<li>\u0421\u0442\u0440\u043e\u043a\u0438 (narrow, wide)<\/li>\n<li>bool<\/li>\n<li>\u041c\u0430\u0441\u0441\u0438\u0432\u044b (\u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043d\u0430 \u0431\u0435\u0437\u0440\u0430\u0437\u043c\u0435\u0438\u043d\u044b\u0435 \u043a\u043e\u0440\u0442\u0435\u0436\u0438)<\/li>\n<li>\u0421\u043b\u043e\u0432\u0430\u0440\u0438<\/li>\n<li>\u041e\u0442\u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 C++-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412\u0441\u0451 \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c \u043d\u0430 \u0431\u0430\u0437\u0435 boost::variant:<\/p>\n<p>  <\/p>\n<pre><code>using ValueData = boost::variant&lt;EmptyValue, bool, std::string, std::wstring, int64_t, double, boost::recursive_wrapper&lt;ValuesList&gt;, boost::recursive_wrapper&lt;ValuesMap&gt;, GenericList, GenericMap&gt;;  class Value { public:     Value() = default;     template&lt;typename T&gt;     Value(T&amp;&amp; val, typename std::enable_if&lt;!std::is_same&lt;std::decay_t&lt;T&gt;, Value&gt;::value&gt;::type* = nullptr)         : m_data(std::forward&lt;T&gt;(val))     {     }     Value(const char* val)         : m_data(std::string(val))     {     }     template&lt;size_t N&gt;     Value(char (&amp;val)[N])         : m_data(std::string(val))     {     }     Value(int val)         : m_data(static_cast&lt;int64_t&gt;(val))     {     }      const ValueData&amp; data() const {return m_data;}      ValueData&amp; data() {return m_data;}  private:     ValueData m_data; };<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/63e67774dd3fad846e50101451a92c50ce1b8441\/include\/jinja2cpp\/value.h#L92\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u0435\u0439 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u044b\u0445 \u0438\u0437 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u041d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0442 \u043d\u0430\u0431\u043e\u0440 \u0442\u0438\u043f\u043e\u0432 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0443\u0437\u043a\u0438\u0439. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0421\u0442\u0440\u043e\u043a\u0430 \u0432 \u0446\u0435\u043b\u0435\u0432\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c narrow \u0438\u043b\u0438 wide \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f.<\/li>\n<li>callable-\u0442\u0438\u043f<\/li>\n<li>\u0423\u0437\u0435\u043b AST-\u0434\u0435\u0440\u0435\u0432\u0430<\/li>\n<li>\u041f\u0430\u0440\u0430 &#171;\u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435&#187;<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u0443\u0442\u0435\u043c \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043d\u0430\u0447\u0435 \u0431\u044b \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c &#171;\u0441\u0432\u0435\u0442\u0438\u0442\u044c&#187; \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u0430\u0447\u043d\u043e \u043e\u0431\u043e\u0449\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438 \u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u044f\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>Boost::variant \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e. \u0415\u0433\u043e \u0431\u043e\u0433\u0430\u0442\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u0412 Jinja2CppLight \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0436\u0435 \u0446\u0435\u043b\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0430 \u0432 inja \u2014 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0442\u0438\u043f\u043e\u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 nlohmann json. \u041e\u0431\u0435 \u044d\u0442\u0438 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b, \u0443\u0432\u044b, \u043c\u043d\u0435 \u043d\u0435 \u043f\u043e\u0434\u043e\u0448\u043b\u0438. \u041f\u0440\u0438\u0447\u0438\u043d\u0430: \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c n-\u0430\u0440\u043d\u043e\u0439 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f boost::variant (\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u2014 \u0438 std::variant). \u0414\u043b\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u0438\u0437\u0438\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0442\u0438\u043f\u0430, \u0438 \u043d\u0430\u0442\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u043f\u0430\u0440\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0418 \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043d\u0430\u0434\u043e! \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u0441 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 union&#8217;\u0430\u043c\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code>struct StringJoiner : BaseVisitor&lt;&gt; {     using BaseVisitor::operator ();      InternalValue operator() (EmptyValue, const std::string&amp; str) const     {         return str;     }      InternalValue operator() (const std::string&amp; left, const std::string&amp; right) const     {         return left + right;     } };<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/63e67774dd3fad846e50101451a92c50ce1b8441\/src\/value_visitors.h#L733\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u0432\u0438\u0437\u0438\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<p>  <\/p>\n<pre><code>InternalValue delimiter = m_args[\"d\"]-&gt;Evaluate(context); for (const InternalValue&amp; val : values) {     if (isFirst)         isFirst = false;     else         result = Apply2&lt;visitors::StringJoiner&gt;(result, delimiter);      result = Apply2&lt;visitors::StringJoiner&gt;(result, val); }<\/code><\/pre>\n<p>  <\/p>\n<p><code>Apply2<\/code> \u0437\u0434\u0435\u0441\u044c \u2014 \u044d\u0442\u043e \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <code>boost::apply_visitor<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u0438\u0437\u0438\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0442\u0438\u043f\u0430 \u043a \u043f\u0430\u0440\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0434\u0435\u043b\u0430\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e. \u0415\u0441\u043b\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0443 \u0432\u0438\u0437\u0438\u0442\u043e\u0440\u0430 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u2014 \u043e\u043d\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0438\u0437\u0438\u0442\u043e\u0440:<\/p>\n<p>  <\/p>\n<pre><code>comparator = [](const KeyValuePair&amp; left, const KeyValuePair&amp; right) {     return ConvertToBool(Apply2&lt;visitors::BinaryMathOperation&gt;(left.value, right.value, BinaryExpression::LogicalLt, BinaryExpression::CaseSensitive)); };<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ql\/6e\/qd\/ql6eqdbjul3yrvjblr0nwjgqet8.png\" align=\"left\" width=\"60%\" height=\"60%\"> \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439: variant(\u044b) -&gt; \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e visitor&#8217;\u0430 -&gt; \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043d\u0430\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u2014 &gt; \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 variant. \u0418 \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043f\u043e\u0434\u043a\u043e\u0432\u0435\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u043a\u0430\u043a \u0432 js: \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f) \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0432\u044b\u0431\u0440\u0430\u0432 \u043d\u0435\u043a\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u0442\u0440\u043e\u043a \u0432 \u0447\u0438\u0441\u043b\u0430, \u0447\u0438\u0441\u0435\u043b \u0432 \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0441\u043f\u0438\u0441\u043a\u0438 \u0438 \u0442. \u043f. \u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0438 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b. \u042f \u0432\u044b\u0431\u0440\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u0443\u0442\u044c: \u0435\u0441\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c (\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439) \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0438\u043b\u0438 \u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0430, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0447\u0438\u0441\u043b\u0430 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438 (&#8216;~&#8217;). \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 AST \u0434\u0435\u043b\u0430\u0442\u044c \u0443\u0436\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<p>  <\/p>\n<h3 id=\"filtry-i-testy\">\u0424\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0442\u0435\u0441\u0442\u044b<\/h3>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/iy\/zr\/pp\/iyzrppwjtrqdunkvflnjf1bv5ak.png\" align=\"right\" width=\"50%\" height=\"50%\"> \u0422\u043e, \u0447\u0442\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439&#187; \u0432 Jinja2 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;\u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438&#187;. \u0412 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0444\u0438\u043b\u044c\u0442\u0440 \u2014 \u044d\u0442\u043e \u043d\u0435\u043a\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c, \u0441\u0442\u043e\u044f\u0449\u0438\u043c \u0441\u043b\u0435\u0432\u0430 \u043e\u0442 \u0437\u043d\u0430\u043a\u0430 &#8216;|&#8217;, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0424\u0438\u043b\u044c\u0442\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443, \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d:<br \/>  <code>{{ menuItems | selectattr('visible') | map(attribute='title') | map('upper') | join(' -&gt; ') }}<\/code><br \/>  \u0417\u0434\u0435\u0441\u044c \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 menuItems \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 visible \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 true, \u043f\u043e\u0442\u043e\u043c \u0443 \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u0437\u044f\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 title, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440, \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0440\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043b\u0435\u0435\u043d \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0435\u043c &#8216; -&gt; &#8216; \u0432 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u043e\u043a\u0443. \u0418\u043b\u0438, \u0441\u043a\u0430\u0436\u0435\u043c, \u0432\u043e \u043f\u0440\u0438\u043c\u0435\u0440 &#171;\u0438\u0437 \u0436\u0438\u0437\u043d\u0438&#187;:<\/p>\n<p>  <\/p>\n<pre><code>{% macro MethodsDecl(class, access) %} {% for method in class.methods | rejectattr('isImplicit') | selectattr('accessType', 'in', access) %} {{ method.fullPrototype }}; {% endfor %} {% endmacro %}<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/flexferrum\/autoprogrammer\/blob\/ace6511e81731d96c89ffd144764ca626075b8e6\/src\/generators\/metaclasses\/metaclasses_generator.cpp#L30\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>{% macro MethodsDecl(class, access) %} {{ for method in class.methods | rejectattr('isImplicit') | selectattr('accessType', 'in', access) | map(attribute='fullPrototype') | join(';\\n') }}; {% endmacro %}<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0430\u043a\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043e\u0442\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 isImplicit \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 true, \u0438\u0437 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0442\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 accessType \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0438\u0445 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u044b. \u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e. \u0418 \u0443\u0436 \u0432\u0441\u044f\u043a\u043e \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0442\u0440\u0435\u0445\u044d\u0442\u0430\u0436\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b \u0438 if&#8217;\u044b \u0433\u043e\u0440\u043e\u0434\u0438\u0442\u044c. \u041a \u0441\u043b\u043e\u0432\u0443, \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u0432 C++ \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/ericniebler.github.io\/std\/wg21\/D4128.html\">range v.3<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u043c\u0430\u0445 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0431\u044b\u043b \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043e\u043a\u043e\u043b\u043e \u0441\u043e\u0440\u043e\u043a\u0430 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0432\u043a\u043b\u044e\u0447\u0438\u043b \u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440. \u0421 \u0447\u0435\u0433\u043e-\u0442\u043e \u044f \u0432\u0437\u044f\u043b, \u0447\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u043b\u044e\u0441\u044c \u0441 \u044d\u0442\u0438\u043c \u0437\u0430 \u043d\u0435\u0434\u0435\u043b\u044e-\u0434\u0440\u0443\u0433\u0443\u044e. \u042d\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e. \u0418 \u0445\u043e\u0442\u044f \u0442\u0438\u043f\u043e\u0432\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430: \u0432\u0437\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a \u043d\u0435\u043c\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0444\u0443\u043d\u043a\u0442\u043e\u0440, \u0438\u0445 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e, \u0438 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f.<br \/>  \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u043a\u043e\u0439 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043b\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u0412 Jinja2, \u043a\u0430\u043a \u0438 \u0432 \u043f\u0438\u0442\u043e\u043d\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432 \u0432\u044b\u0437\u043e\u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435, \u0442\u0430\u043a \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0435. \u0410 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435, \u0442\u0430\u043a \u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 (\u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e). \u041f\u0440\u0438\u0447\u0451\u043c, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 C++, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f. \u041d\u0430\u0434\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043e\u0432\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u0435\u0439\u0441\u043e\u0432. \u0412\u043e\u0442, \u0441\u043a\u0430\u0436\u0435\u043c, \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f range: <code>range([start, ]stop[, step])<\/code>. \u041e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<pre><code>range(10) \/\/ -&gt; range(start = 0, stop = 10, step = 1) range(1, 10) \/\/ -&gt; range(start = 1, stop = 10, step = 1) range(1, 10, 3) \/\/ -&gt; range(start = 1, stop = 10, step = 3) range(step=2, 10) \/\/ -&gt; range(start = 0, stop = 10, step = 2) range(2, step=2, 10) \/\/ -&gt; range(start = 2, stop = 10, step = 2)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0418 \u043e\u0447\u0435\u043d\u044c \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u0432 \u043a\u043e\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u0441\u0435 \u044d\u0442\u0438 \u043a\u0435\u0439\u0441\u044b \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430, \u0442\u0435\u0441\u0442\u0435\u0440\u0430 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e \u0438\u043c\u0435\u043d\u0438. \u0418 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0435\u043c \u0438\u043b\u0438 \u0438\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0437\u0430\u0434\u0430\u043d\u044b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0411\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u0443\u0441\u043e\u043a \u043a\u043e\u0434\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">ParsedArguments ParseCallParams(const std::initializer_list&lt;ArgumentInfo&gt;&amp; args, const CallParams&amp; params, bool&amp; isSucceeded) {     struct ArgInfo     {         ArgState state = NotFound;         int prevNotFound = -1;         int nextNotFound = -1;         const ArgumentInfo* info = nullptr;     };      boost::container::small_vector&lt;ArgInfo, 8&gt; argsInfo(args.size());     boost::container::small_vector&lt;ParamState, 8&gt; posParamsInfo(params.posParams.size());      isSucceeded = true;      ParsedArguments result;      int argIdx = 0;     int firstMandatoryIdx = -1;     int prevNotFound = -1;     int foundKwArgs = 0;      \/\/ Find all provided keyword args     for (auto&amp; argInfo : args)     {         argsInfo[argIdx].info = &amp;argInfo;         auto p = params.kwParams.find(argInfo.name);         if (p != params.kwParams.end())         {             result.args[argInfo.name] = p-&gt;second;             argsInfo[argIdx].state = Keyword;             ++ foundKwArgs;         }         else         {             if (argInfo.mandatory)             {                 argsInfo[argIdx].state = NotFoundMandatory;                 if (firstMandatoryIdx == -1)                     firstMandatoryIdx = argIdx;             }             else             {                 argsInfo[argIdx].state = NotFound;             }              if (prevNotFound != -1)                 argsInfo[prevNotFound].nextNotFound = argIdx;              argsInfo[argIdx].prevNotFound = prevNotFound;             prevNotFound = argIdx;         }          ++ argIdx;     }      int startPosArg = firstMandatoryIdx == -1 ? 0 : firstMandatoryIdx;     int curPosArg = startPosArg;     int eatenPosArgs = 0;      \/\/ Determine the range for positional arguments scanning     bool isFirstTime = true;     for (; eatenPosArgs &lt; posParamsInfo.size(); ++ eatenPosArgs)     {         if (isFirstTime)         {             for (; startPosArg &lt; args.size() &amp;&amp; (argsInfo[startPosArg].state == Keyword || argsInfo[startPosArg].state == Positional); ++ startPosArg)                 ;              isFirstTime = false;             continue;         }          int prevNotFound = argsInfo[startPosArg].prevNotFound;         if (prevNotFound != -1)         {             startPosArg = prevNotFound;         }         else if (curPosArg == args.size())         {             break;         }         else         {             int nextPosArg = argsInfo[curPosArg].nextNotFound;             if (nextPosArg == -1)                 break;             curPosArg = nextPosArg;         }     }      \/\/ Map positional params to the desired arguments     int curArg = startPosArg;     for (int idx = 0; idx &lt; eatenPosArgs &amp;&amp; curArg != -1; ++ idx, curArg = argsInfo[curArg].nextNotFound)     {         result.args[argsInfo[curArg].info-&gt;name] = params.posParams[idx];         argsInfo[curArg].state = Positional;     }      \/\/ Fill default arguments (if missing) and check for mandatory     for (int idx = 0; idx &lt; argsInfo.size(); ++ idx)     {         auto&amp; argInfo = argsInfo[idx];         switch (argInfo.state)         {         case Positional:         case Keyword:             continue;         case NotFound:         {             if (!IsEmpty(argInfo.info-&gt;defaultVal))                 result.args[argInfo.info-&gt;name] = std::make_shared&lt;ConstantExpression&gt;(argInfo.info-&gt;defaultVal);             break;         }         case NotFoundMandatory:             isSucceeded = false;             break;         }     }      \/\/ Fill the extra positional and kw-args     for (auto&amp; kw : params.kwParams)     {         if (result.args.find(kw.first) != result.args.end())             continue;          result.extraKwArgs[kw.first] = kw.second;     }      for (auto idx = eatenPosArgs; idx &lt; params.posParams.size(); ++ idx)         result.extraPosArgs.push_back(params.posParams[idx]);      return result; }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/6331e7bdf31c229589452b1cbfc68f262029dae5\/src\/expression_evaluator.cpp#L369\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043d \u0442\u0430\u043a\u0438\u043c \u0432\u043e\u0442 \u043e\u0431\u0440\u0430\u0437\u043e\u043c (\u0434\u043b\u044f, \u0441\u043a\u0430\u0436\u0435\u043c, <code>range<\/code>):<\/p>\n<p>  <\/p>\n<pre><code>bool isArgsParsed = true;  auto args = helpers::ParseCallParams({{\"start\"}, {\"stop\", true}, {\"step\"}}, m_params, isArgsParsed); if (!isArgsParsed)     return InternalValue();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<p>  <\/p>\n<pre><code>struct ParsedArguments {     std::unordered_map&lt;std::string, ExpressionEvaluatorPtr&lt;&gt;&gt; args;     std::unordered_map&lt;std::string, ExpressionEvaluatorPtr&lt;&gt;&gt; extraKwArgs;     std::vector&lt;ExpressionEvaluatorPtr&lt;&gt;&gt; extraPosArgs;      ExpressionEvaluatorPtr&lt;&gt; operator[](std::string name) const     {         auto p = args.find(name);         if (p == args.end())             return ExpressionEvaluatorPtr&lt;&gt;();          return p-&gt;second;     } };<\/code><\/pre>\n<p>  <\/p>\n<p>\u043d\u0443\u0436\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u0438:<\/p>\n<p>  <\/p>\n<pre><code>auto startExpr = args[\"start\"]; auto stopExpr = args[\"stop\"]; auto stepExpr = args[\"step\"];  InternalValue startVal = startExpr ? startExpr-&gt;Evaluate(values) : InternalValue(); InternalValue stopVal = stopExpr ? stopExpr-&gt;Evaluate(values) : InternalValue(); InternalValue stepVal = stepExpr ? stepExpr-&gt;Evaluate(values) : InternalValue();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043c\u0430\u043a\u0440\u043e\u0441\u0430\u043c\u0438 \u0438 \u0442\u0435\u0441\u0442\u0435\u0440\u0430\u043c\u0438. \u0418 \u0445\u043e\u0442\u044f, \u0432\u0440\u043e\u0434\u0435 \u0431\u044b, \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0438 \u0442\u0435\u0441\u0442\u0430, \u043d\u0435\u0442 (\u043a\u0430\u043a \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e), \u043d\u043e \u0434\u0430\u0436\u0435 &#171;\u0431\u0430\u0437\u043e\u0432\u044b\u0439&#187; \u043d\u0430\u0431\u043e\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0448\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u044f\u0442\u044c\u0434\u0435\u0441\u044f\u0442 \u0442\u0435\u0445 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445, \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u044a\u0451\u043c\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0418 \u044d\u0442\u043e \u043f\u0440\u0438 \u0442\u043e\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0432 \u043d\u0435\u0433\u043e \u043d\u0435 \u0432\u043e\u0448\u043b\u0438 \u0432\u0441\u044f\u043a\u0438\u0435 \u0445\u0438\u0442\u0440\u044b\u0435 \u0448\u0442\u0443\u043a\u0438, \u043a\u0430\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a \u043f\u043e\u0434 HTML (\u0438\u043b\u0438 C++), \u0432\u044b\u0432\u043e\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445 \u0442\u0438\u043f\u0430 xml \u0438\u043b\u0438 json, \u0438 \u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0432\u0435\u0449\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 (export, include, \u043c\u0430\u043a\u0440\u043e\u0441\u044b), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e \u0443\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b.<\/p>\n<p>  <\/p>\n<p>\u0422\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e, \u0441\u0441\u044b\u043b\u043a\u0438:<br \/>  \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f Jinja2: <a href=\"http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/\"><\/a><a href=\"http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/\">http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/<\/a><br \/>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Jinja2Cpp: <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\"><\/a><a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\">https:\/\/github.com\/flexferrum\/Jinja2Cpp<\/a><\/p>\n<\/div>\n<p>        <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <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\/post\/419011\/\"> https:\/\/habr.com\/post\/419011\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/419011\/\" class=\"post__text post__text-html js-mediator-article\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c81\/fe0\/548\/c81fe0548837b911b9569cdf49d90ca2.jpg\" alt=\"Jinja2 logo\" align=\"left\"> \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043e \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 Jinja2 \u043d\u0430 C++. \u041f\u0435\u0440\u0432\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/habr.com\/post\/416581\/\">\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430, \u0438\u043b\u0438 \u043a\u0430\u043a \u044f \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b Jinja2 \u043d\u0430 C++<\/a>. \u0412 \u043d\u0435\u0439 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432. \u0418\u043b\u0438, \u0438\u043d\u0430\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 &#171;\u0441 \u043d\u0443\u043b\u044f&#187; \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043f\u0438\u0442\u043e\u043d\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\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-288311","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288311","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=288311"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288311\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=288311"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=288311"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=288311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}