{"id":223865,"date":"2014-05-23T02:41:02","date_gmt":"2014-05-22T22:41:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=223865"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=223865","title":{"rendered":"<span class=\"post_title\">\u0412\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435<\/span>"},"content":{"rendered":"<div class=\"content html_format\">     \t\u041f\u0440\u0438\u0432\u0435\u0442!<br \/>  \u041d\u0435 \u0437\u043d\u0430\u043b, \u043a\u0430\u043a \u043f\u043e\u0442\u043e\u0447\u043d\u0435\u0435 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0432\u0443\u0447\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<blockquote><p>\u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u0442\u0440\u043e\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0438\u043c\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0435\u0451 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u041d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.<\/p><\/blockquote>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a <a href=\"http:\/\/help.adobe.com\/en_US\/ActionScript\/3.0_ProgrammingAS3\/WS5b3ccc516d4fbf351e63e3d118a9b90204-7caf.html\">ActionScript<\/a> \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <u>test<\/u> \u0441 \u0442\u0440\u0435\u043c\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 <i>str<\/i>, <i>false<\/i>, <i>1.0<\/i>(\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432: <i>String<\/i>, <i>Boolean<\/i>, <i>Number<\/i>):  <\/p>\n<pre><code class=\"xml\">&lt;invoke name=&quot;test&quot; returntype=&quot;xml&quot;&gt;&lt;arguments&gt;&lt;string&gt;str&lt;\/string&gt;&lt;false\/&gt;&lt;number&gt;1.0&lt;\/number&gt;&lt;\/arguments&gt;&lt;\/invoke&gt; <\/code><\/pre>\n<p>  \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b C++ \u0431\u044b\u043b\u0430 \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:  <\/p>\n<pre><code class=\"cpp\">void test_handler(const std::wstring& str, bool flag, double n); <\/code><\/pre>\n<p>  \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 \u0438, \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430(\u0438 \u043a\u0430\u043f\u0435\u043b\u044c\u043a\u0438 boost-\u0430).<br \/>  <a name=\"habracut\"><\/a><br \/>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u043e \u043d\u0435 \u0441\u0443\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u043e, \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430 xml, \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_55_0\/doc\/html\/property_tree.html\">Boost.PropertyTree<\/a>. \u0412\u0441\u0451 \u044d\u0442\u043e \u0441\u043f\u0440\u044f\u0447\u0435\u043c \u0432 \u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>InvokeParser<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c <i>\u0438\u043c\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/i> \u0438 \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u0430\u0440 <i>\u0442\u0438\u043f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430-\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/i>:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">InvokeParser<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &quot;boost\/property_tree\/ptree.hpp&quot; #include &quot;boost\/property_tree\/xml_parser.hpp&quot;  namespace as3 {  class InvokeParser { public: \tusing ArgsContainer = std::vector&lt; \t\tstd::pair&lt; \t\t\tstd::wstring, \/\/ Argument type \t\t\tstd::wstring \/\/ Argument value \t\t\t&gt;&gt;;  public: \tInvokeParser() \t\t: invoke_name_() \t\t, arguments_() \t{ \t}  \tbool parse(const std::wstring& str) \t{ \t\tusing namespace boost; \t\tusing namespace boost::property_tree;  \t\ttry \t\t{ \t\t\tstd::wistringstream stream(str); \t\t\twptree xml; \t\t\tread_xml(stream, xml);  \t\t\t\/\/ Are 'invoke' tag attributes and 'arguments' tag exists? \t\t\tauto invoke_attribs = xml.get_child_optional(L&quot;invoke.&lt;xmlattr&gt;&quot;); \t\t\tauto arguments_xml = xml.get_child_optional(L&quot;invoke.arguments&quot;); \t\t\tif(!invoke_attribs || !arguments_xml) \t\t\t\treturn false; \t\t\t\/\/ Is 'name' exists ? \t\t\tauto name = invoke_attribs-&gt;get_optional&lt;std::wstring&gt;(L&quot;name&quot;); \t\t\tif(!name) \t\t\t\treturn false; \t\t\tinvoke_name_ = *name;  \t\t\targuments_.reserve(arguments_xml-&gt;size()); \t\t\tfor(const auto& arg_value_pair : *arguments_xml) \t\t\t{ \t\t\t\tstd::wstring arg_type = arg_value_pair.first; \t\t\t\tstd::wstring arg_value = arg_value_pair.second.get_value(L&quot;&quot;); \t\t\t\tif((arg_type == L&quot;true&quot;) || (arg_type == L&quot;false&quot;)) \t\t\t\t{ \t\t\t\t\targ_value = arg_type; \t\t\t\t\targ_type = L&quot;bool&quot;; \t\t\t\t}  \t\t\t\targuments_.emplace_back(arg_type, arg_value); \t\t\t}  \t\t\treturn true; \t\t} \t\tcatch(const boost::property_tree::xml_parser_error& \/*parse_exc*\/) \t\t{ \t\t} \t\tcatch(...) \t\t{ \t\t} \t\treturn false; \t}  \tstd::wstring function_name() const \t{ \t\treturn invoke_name_; \t}  \tsize_t arguments_count() const \t{ \t\treturn arguments_.size(); \t}  \tconst ArgsContainer& arguments() const \t{ \t\treturn arguments_; \t}  private: \tstd::wstring invoke_name_; \tArgsContainer arguments_; }; } \/\/ as3 <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>Type<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u2014 \u043d\u0435\u043a\u0438\u0439 C++-\u0442\u0438\u043f, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0438\u043c\u044f \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b ActionScript. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:  <\/p>\n<pre><code class=\"cpp\">Type&lt;short&gt;::convert(L&quot;20&quot;); \/\/ \u0412\u0435\u0440\u043d\u0451\u0442 20, \u0442\u0438\u043f short Type&lt;short&gt;::name(); \/\/ short \u0434\u043b\u044f ActionScript \u044d\u0442\u043e &quot;number&quot; <\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>Type<\/code>:  <\/p>\n<pre><code class=\"cpp\">template&lt;typename CppType&gt; struct Type : \tstd::enable_if&lt; \t\t!std::is_array&lt;CppType&gt;::value, \t\tTypeHelper&lt; \t\t\ttypename std::decay&lt;CppType&gt;::type&gt; \t&gt;::type { };  template&lt;typename CppType&gt; struct Type&lt;CppType*&gt; { }; <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043d\u0435\u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0435\u043b\u044c\u0437\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c \u043d\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0442\u0438\u043f, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438(\u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0434\u043b\u044f <i>ActionScript<\/i> \u2014 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u043f\u0440\u043e\u0441\u0442\u0443 \u043d\u0435\u0442). \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0432\u0441\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0440\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<br \/>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u043e\u0431\u043e\u0442\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>TypeHelper<\/code>. <code>TypeHelper<\/code> \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u00ab\u0433\u043e\u043b\u044b\u043c\u00bb \u0442\u0438\u043f\u043e\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f <code>const std::wstring&<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f <code>std::wstring<\/code> \u0438 \u0442.\u0434. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/types\/decay\">decay<\/a>. \u0418 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0440\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u044e\u0442 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0442\u0438\u043f\u0430 <code>f(const std::wstring&)<\/code> \u0438 <code>f(std::wstring)<\/code>. \u0414\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0441\u043b\u0443\u0448\u043d\u044b\u0439 <code>decay<\/code> \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u043e\u0431\u043e\u0442\u043e\u0439 \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0442\u043e, \u0447\u0442\u043e \u0445\u043e\u0442\u0435\u043b\u0438.<\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d <code>TypeHelper<\/code>. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0447\u0438\u0441\u0435\u043b. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/types\">\u0410\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445<\/a> \u0442\u0438\u043f\u043e\u0432, \u0445\u043e\u0442\u044f, \u043f\u043e-\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443, \u043d\u0443\u0436\u043d\u043e-\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0442\u0438\u043f\u044b(\u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0432 <code>is_valid_type<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>std::is_same<\/code>).  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">TypeHelper<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">template&lt;typename CppType&gt; struct TypeHelper { private: \tenum { is_valid_type = std::is_arithmetic&lt;CppType&gt;::value }; public: \ttypedef typename std::enable_if&lt;is_valid_type, CppType&gt;::type Type;  \tstatic typename std::enable_if&lt;is_valid_type, std::wstring&gt;::type name() \t{ \t\treturn L&quot;number&quot;; \t}  \t\/\/ Convert AS3 number type from string to @CppType \tstatic Type convert(const std::wstring& str) \t{ \t\tdouble value = std::stod(str); \t\treturn static_cast&lt;Type&gt;(value); \t} }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0438\u043c\u044f \u0432\u0441\u0435\u0445 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 <i>ActionScript<\/i> \u2014 <u>number<\/u>. \u0414\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0432 <code>double<\/code>, \u0430 \u043f\u043e\u0442\u043e\u043c \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0442\u0438\u043f.<br \/>  \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 <code>bool<\/code>, <code>std::wstring<\/code> \u0438 <code>void<\/code>:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u043d\u044b\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 TypeHelper \u0434\u043b\u044f bool, std::wstring, void<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">template&lt;&gt; struct TypeHelper&lt;bool&gt; { \ttypedef bool Type;  \tstatic std::wstring name() \t{ \t\treturn L&quot;bool&quot;; \t}  \tstatic bool convert(const std::wstring& str) \t{ \t\treturn (str == L&quot;true&quot;); \t} };  template&lt;&gt; struct TypeHelper&lt;std::wstring&gt; { \ttypedef std::wstring Type;  \tstatic std::wstring name() \t{ \t\treturn L&quot;string&quot;; \t}  \tstatic std::wstring convert(const std::wstring& str) \t{ \t\treturn str; \t} };  template&lt;&gt; struct TypeHelper&lt;void&gt; { \ttypedef void Type;  \tstatic std::wstring name() \t{ \t\treturn L&quot;undefined&quot;; \t}  \tstatic void convert(const std::wstring& \/*str*\/) \t{ \t} }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u043e\u0442 \u0438 \u0432\u0441\u0451, \u043f\u043e-\u0441\u0443\u0442\u0438! \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439(\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u0438 \u0442.\u0434.), \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>IFunction<\/code>:  <\/p>\n<pre><code class=\"cpp\">struct IFunction { \tvirtual bool call(const InvokeParser& parser) = 0; \t \tvirtual ~IFunction() \t{ \t} }; <\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u044b-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 \u0443\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f. \u0421\u043d\u043e\u0432\u0430 \u0448\u0430\u0431\u043b\u043e\u043d:  <\/p>\n<pre><code class=\"cpp\">template&lt;typename ReturnType, typename... Args&gt; struct Function : \tpublic IFunction { \tFunction(const std::wstring& function_name, ReturnType (*f)(Args...)) \t\t: f_(f) \t\t, name_(function_name) \t{ \t} \t \tbool call(const InvokeParser& parser) \t{ \t\tif(name_ != parser.function_name()) \t\t\treturn false; \t\tconst auto ArgsCount = sizeof...(Args); \t\tif(ArgsCount != parser.arguments_count()) \t\t\treturn false;  \t\tauto indexes = typename generate_sequence&lt;ArgsCount&gt;::type(); \t\tauto args = parser.arguments();  \t\tif(!validate_types(args, indexes)) \t\t\treturn false;  \t\treturn call(args, indexes); \t}  private: \ttemplate&lt;int... S&gt; \tbool validate_types(const InvokeParser::ArgsContainer& args, sequence&lt;S...&gt;) \t{ \t\tstd::array&lt;std::wstring, sizeof...(Args)&gt; cpp_types = { Type&lt;Args&gt;::name()... }; \t\tstd::array&lt;std::wstring, sizeof...(S)&gt; as3_types = { args[S].first... }; \t\treturn (cpp_types == as3_types); \t}  \ttemplate&lt;int... S&gt; \tbool call(const InvokeParser::ArgsContainer& args, sequence&lt;S...&gt;) \t{ \t\tf_(Type&lt;Args&gt;::convert(args[S].second)...); \t\treturn true; \t}  protected: \tstd::function&lt;ReturnType (Args...)&gt; f_; \tstd::wstring name_; };  template&lt;typename ReturnType, typename... Args&gt; std::shared_ptr&lt;IFunction&gt; make_function(const std::wstring& as3_function_name, ReturnType (*f)(Args...)) { \treturn std::make_shared&lt;Function&lt;ReturnType, Args...&gt;&gt;(as3_function_name, f); } <\/code><\/pre>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:  <\/p>\n<pre><code class=\"cpp\">void test_handler(const std::wstring& str, bool flag, double n) { \tstd::wcout &lt;&lt; L&quot;test: &quot; &lt;&lt; str &lt;&lt; L&quot;, &quot; &lt;&lt; std::boolalpha &lt;&lt; flag &lt;&lt; &quot;, &quot; &lt;&lt; n &lt;&lt; std::endl; }  int main() { \tas3::InvokeParser parser; \tstd::wstring str = L&quot;&lt;invoke name=\\&quot;test\\&quot; returntype=\\&quot;xml\\&quot;&gt;&quot; \t\tL&quot;&lt;arguments&gt;&lt;string&gt;str&lt;\/string&gt;&lt;false\/&gt;&lt;number&gt;1.0&lt;\/number&gt;&lt;\/arguments&gt;&quot; \t\tL&quot;&lt;\/invoke&gt;&quot;; \tif(parser.parse(str)) \t{ \t\tauto function = as3::make_function(L&quot;test&quot;, test_handler); \t\tfunction-&gt;call(parser); \t} } <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0434\u0435\u0442\u0430\u043b\u044f\u043c. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0435\u0441\u0442\u044c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>as3::make_function()<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u0442\u0438\u043f\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e callback-\u0430.<br \/>  \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0439\u0442\u0438\u0441\u044c(\u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u2014 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u00ab\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u00bb, \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 <i>Parameter pack<\/i>(\u043d\u0438\u0436\u0435)) \u043f\u043e \u043f\u0430\u043a\u0435\u0442\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432(\u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438? <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack\">Parameter pack<\/a>) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b <code>sequence<\/code> \u0438 <code>generate_sequence<\/code>:  <\/p>\n<pre><code class=\"cpp\">template&lt;size_t N, size_t... Sequence&gt; struct generate_sequence : \tgenerate_sequence&lt;N - 1, N - 1, Sequence...&gt; { };  template&lt;size_t...&gt; struct sequence { };  template&lt;int... Sequence&gt; struct generate_sequence&lt;0, Sequence...&gt; { \ttypedef sequence&lt;Sequence...&gt; type; }; <\/code><\/pre>\n<p>  \u041f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u043d\u0430 <a href=\"http:\/\/stackoverflow.com\/questions\/7858817\/unpacking-a-tuple-to-call-a-matching-function-pointer\">stackoverflow<\/a>.<br \/>  \u0412 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 <code>generate_sequence&lt;N&gt;<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 <code>0, 1, 2, ... N - 1<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f(\u0447\u0438\u0442\u0430\u0442\u044c: \u00ab\u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c\u00bb) \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>sequence<\/code>. \u042d\u0442\u043e \u0432\u0441\u0451 \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f <i>Pack expansion<\/i>(\u0431\u0443\u0434\u0443 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u0430\u043a \u00ab\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u0430\u00bb).<br \/>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<br \/>  \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0430\u043a\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 <code>typename... Args<\/code> \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>f<\/code>. \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>f<\/code>, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043a\u0430\u0436\u0434\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c <code>f<\/code>:  <\/p>\n<pre><code class=\"cpp\">template&lt;typename... Args&gt; struct Test { \ttemplate&lt;int... S&gt; \tstatic bool test(const std::vector&lt;pair&lt;int, float&gt;&gt;& args, sequence&lt;S...&gt;) \t{ \t\tf_(Type&lt;Args&gt;::convert(args[S].second)...); \t\treturn true; \t}\t }; \/\/ \u0433\u0434\u0435-\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 test(args, typename generate_sequence&lt;sizeof...(Args)&gt;::type()) <\/code><\/pre>\n<p>  \u0412\u044b\u0437\u043e\u0432 <code>test<\/code> \u0434\u043b\u044f <code>Args = &lt;int, float&gt;<\/code> \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432 \u0432\u044b\u0437\u043e\u0432:  <\/p>\n<pre><code class=\"cpp\">f_(Type&lt;int&gt;::convert(args[0].second), Type&lt;float&gt;::convert(args[1].second)) <\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u0438 \u0432\u0441\u044f \u043c\u0430\u0433\u0438\u044f!<br \/>  \u041d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u0447\u043b\u0435\u043d <code>Function::validate_types<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0434\u0432\u0430 \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u041e\u0434\u0438\u043d \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043c\u0435\u043d\u0430 <i>C++<\/i>-\u0442\u0438\u043f\u043e\u0432 \u0432 <i>ActionScript-\u0435<\/i>, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u0438\u043c\u0435\u043d\u0430 \u0442\u0438\u043f\u043e\u0432, \u0441\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u0415\u0441\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u043d\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b \u2014 \u0443 \u043d\u0430\u0441 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430\u044f \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438! \u0418 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0412\u043e\u0442 \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u043e\u0449\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432!<br \/>  \u0410 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u0447\u043b\u0435\u043d <code>call(const InvokeParser::ArgsContainer& args, sequence&lt;S...&gt;)<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f.<br \/>  \u0412\u0441\u0451 \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>make_function()<\/code> \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u0439 \u0442\u0438\u043f <code>IFunction<\/code>, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435(\u0434\u0430 \u0432 \u0447\u0451\u043c \u0443\u0433\u043e\u0434\u043d\u043e) \u0438 \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u0434 \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430, \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0432\u043d\u043e\u0433\u043e \u0447\u0435\u0442\u044b\u0440\u0451\u043c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>boost::function_traits<\/code> \u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e <code>mpl<\/code> \ud83d\ude42<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">InvokeParser<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">class InvokeParser { public: \ttypedef std::vector&lt;std::pair&lt;std::wstring, std::wstring&gt; &gt; ArgsContainer; \ttypedef ArgsContainer::value_type TypeValuePair;  public: \tInvokeParser() \t\t: invoke_name_() \t\t, arguments_() \t{ \t}  \tbool parse(const std::wstring& str) \t{ \t\tusing namespace boost; \t\tusing namespace boost::property_tree;  \t\ttry \t\t{ \t\t\tstd::wistringstream stream(str); \t\t\twptree xml; \t\t\tread_xml(stream, xml);  \t\t\toptional&lt;wptree&&gt; invoke_attribs = xml.get_child_optional(L&quot;invoke.&lt;xmlattr&gt;&quot;); \t\t\toptional&lt;wptree&&gt; arguments_xml = xml.get_child_optional(L&quot;invoke.arguments&quot;); \t\t\tif(!invoke_attribs || !arguments_xml) \t\t\t\treturn false; \t\t\toptional&lt;std::wstring&gt; name = invoke_attribs-&gt;get_optional&lt;std::wstring&gt;(L&quot;name&quot;); \t\t\tif(!name) \t\t\t\treturn false; \t\t\tinvoke_name_ = *name;  \t\t\targuments_.reserve(arguments_xml-&gt;size()); \t\t\tfor(wptree::const_iterator arg_value_pair = arguments_xml-&gt;begin(), end = arguments_xml-&gt;end(); arg_value_pair != end; ++arg_value_pair) \t\t\t{ \t\t\t\tstd::wstring arg_type = arg_value_pair-&gt;first; \t\t\t\tstd::wstring arg_value = arg_value_pair-&gt;second.get_value(L&quot;&quot;); \t\t\t\tif((arg_type == L&quot;true&quot;) || (arg_type == L&quot;false&quot;)) \t\t\t\t{ \t\t\t\t\targ_value = arg_type; \t\t\t\t\targ_type = L&quot;bool&quot;; \t\t\t\t}  \t\t\t\targuments_.push_back(TypeValuePair(arg_type, arg_value)); \t\t\t}  \t\t\treturn true; \t\t} \t\tcatch(const boost::property_tree::xml_parser_error& \/*parse_exc*\/) \t\t{ \t\t} \t\tcatch(...) \t\t{ \t\t} \t\treturn false; \t}  \tstd::wstring function_name() const \t{ \t\treturn invoke_name_; \t}  \tsize_t arguments_count() const \t{ \t\treturn arguments_.size(); \t}  \tconst ArgsContainer& arguments() const \t{ \t\treturn arguments_; \t}  private: \tstd::wstring invoke_name_; \tArgsContainer arguments_; }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">TypeHelper<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">template&lt;typename CppType&gt; struct TypeHelper { private: \t\/\/ Arithmetic types are http:\/\/en.cppreference.com\/w\/cpp\/language\/types. \t\/\/ Need to exclude 'Character types' from this list \t\/\/ (For 'Boolean type' this template has full specialization) \ttypedef boost::mpl::and_&lt; \t\tboost::is_arithmetic&lt;CppType&gt;, \t\tboost::mpl::not_&lt;boost::is_same&lt;CppType, char&gt; &gt;, \t\tboost::mpl::not_&lt;boost::is_same&lt;CppType, wchar_t&gt; &gt;, \t\tboost::mpl::not_&lt;boost::is_same&lt;CppType, unsigned char&gt; &gt;, \t\tboost::mpl::not_&lt;boost::is_same&lt;CppType, signed char&gt; &gt; &gt; ValidCppType; public: \t\/\/ We can get C++ type name equivalent for AS3 &quot;number&quot; type only if \t\/\/ C++ type @CppType is @ValidCppType(see above) \ttypedef typename boost::enable_if&lt; \t\tValidCppType, \t\tCppType&gt;::type Type;  \t\/\/ Get AS3 type name for given @CppType(see @ValidCppType) \tstatic \ttypename boost::enable_if&lt; \t\tValidCppType, \t\tstd::wstring&gt;::type name() \t{ \t\treturn L&quot;number&quot;; \t}  \t\/\/ Convert AS3 number type from string to @CppType(see @ValidCppType) \tstatic \tType convert(const std::wstring& str) \t{ \t\tdouble value = from_string&lt;wchar_t, double&gt;(str); \t\t\/\/ TODO: Use boost type cast \t\treturn static_cast&lt;Type&gt;(value); \t} };  template&lt;&gt; struct TypeHelper&lt;bool&gt; { \ttypedef bool Type;  \t\/\/ AS3 type name for boolean type \tstatic std::wstring name() \t{ \t\treturn L&quot;bool&quot;; \t}  \t\/\/ Convert AS3 boolean value from string to our bool \tstatic bool convert(const std::wstring& str) \t{ \t\treturn (str == L&quot;true&quot;); \t} };  template&lt;&gt; struct TypeHelper&lt;std::wstring&gt; { \ttypedef std::wstring Type;  \tstatic std::wstring name() \t{ \t\treturn L&quot;string&quot;; \t}  \tstatic std::wstring convert(const std::wstring& str) \t{ \t\t\/\/ Ok, do nothing \t\treturn str; \t} };  template&lt;&gt; struct TypeHelper&lt;void&gt; { \ttypedef void Type;  \t\/\/ AS3 type name for void type.. \tstatic std::wstring name() \t{ \t\treturn L&quot;undefined&quot;; \t}  \tstatic void convert(const std::wstring& \/*str*\/) \t{ \t\t\/\/ Oops.. \t\tASSERT_MESSAGE(false, &quot;Can't convert from sring to void&quot;); \t} };  \/\/ @TypeHelper provides implementation \/\/ only for &quot;number&quot; type(arithmetic, without characters type), bool, string and void. \/\/ For any other type @TypeHelper will be empty. \/\/ decay is used for removing cv-qualifier. But it's not what we want for arrays. \/\/ That's why using enable_if template&lt;typename CppType&gt; struct FlashType : \tboost::enable_if&lt; \t\tboost::mpl::not_&lt; \t\t\tboost::is_array&lt;CppType&gt; &gt;, \t\tTypeHelper&lt; \t\t\ttypename std::tr1::decay&lt;CppType&gt;::type&gt; \t&gt;::type { };  \/\/ Partial specialization for pointers \/\/ There is no conversion from AS3 type to C++ pointer.. template&lt;typename CppType&gt; struct FlashType&lt;CppType*&gt; { \t\/\/ static assert }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u043e, \u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u044b\u043b\u043e \u0440\u0430\u043d\u0435\u0435 \u2014 <code>FunctionCaller<\/code> \u2014 <u>\u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0443&#8230;.<\/u>:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">FunctionCaller<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">template&lt;int N&gt; struct FunctionCaller { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function \/*f*\/, const InvokeParser::ArgsContainer& \/*args*\/ #if defined(DEBUG) \t\t, const std::wstring& \/*dbg_function_name*\/ #endif \t\t) \t{ \t\tASSERT_MESSAGE_AND_RETURN_VALUE( \t\t\tfalse, \t\t\t&quot;Provide full FunctionCaller specialization for given arguments count&quot;, \t\t\tfalse); \t} };  template&lt;&gt; struct FunctionCaller&lt;0&gt; { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function f, const InvokeParser::ArgsContainer& \/*args*\/ #if defined(DEBUG) \t\t, const std::wstring& \/*dbg_function_name*\/ #endif \t\t) \t{ \t\t\/\/ Call function without args \t\tf(); \t\treturn true; \t} };  template&lt;&gt; struct FunctionCaller&lt;1&gt; { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function f, const InvokeParser::ArgsContainer& args #if defined(DEBUG) \t\t, const std::wstring& dbg_function_name #endif \t\t) \t{ \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg1_type&gt; Arg1;\t\t \t\tconst InvokeParser::TypeValuePair& arg = args[0]; \t\tif(Arg1::name() != arg.first) \t\t{ #if defined(DEBUG) \t\t\t::OutputDebugStringW(Sprintf&lt;wchar_t&gt;( \t\t\t\tL&quot;Function: \\&quot;%s\\&quot;:\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot;, \t\t\t\tdbg_function_name.c_str(), \t\t\t\tArg1::name().c_str(), arg.first.c_str()).c_str()); #endif \t\t\tASSERT_MESSAGE_AND_RETURN_VALUE(false, &quot;Type mismatch&quot;, false); \t\t} \t\t\/\/ Call function with 1 arg \t\tf(Arg1::convert(arg.second)); \t\treturn true; \t} };  template&lt;&gt; struct FunctionCaller&lt;2&gt; { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function f, const InvokeParser::ArgsContainer& args #if defined(DEBUG) \t\t, const std::wstring& dbg_function_name #endif \t\t) \t{ \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg1_type&gt; Arg1; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg2_type&gt; Arg2; \t\tconst InvokeParser::TypeValuePair& arg1 = args[0]; \t\tconst InvokeParser::TypeValuePair& arg2 = args[1];  \t\tif((Arg1::name() != arg1.first) || \t\t\t(Arg2::name() != arg2.first)) \t\t{ #if defined(DEBUG) \t\t\t::OutputDebugStringW(Sprintf&lt;wchar_t&gt;( \t\t\t\tL&quot;Function: \\&quot;%s\\&quot;:\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot;, \t\t\t\tdbg_function_name.c_str(), \t\t\t\tArg1::name().c_str(), arg1.first.c_str(), \t\t\t\tArg2::name().c_str(), arg2.first.c_str()).c_str()); #endif \t\t\tASSERT_MESSAGE_AND_RETURN_VALUE(false, &quot;Type mismatch&quot;, false); \t\t} \t\t\/\/ Call function with 2 args \t\tf(Arg1::convert(arg1.second), \t\t\tArg2::convert(arg2.second)); \t\treturn true; \t} };  template&lt;&gt; struct FunctionCaller&lt;3&gt; { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function f, const InvokeParser::ArgsContainer& args #if defined(DEBUG) \t\t, const std::wstring& dbg_function_name #endif \t\t) \t{ \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg1_type&gt; Arg1; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg2_type&gt; Arg2; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg3_type&gt; Arg3; \t\tconst InvokeParser::TypeValuePair& arg1 = args[0]; \t\tconst InvokeParser::TypeValuePair& arg2 = args[1]; \t\tconst InvokeParser::TypeValuePair& arg3 = args[2];  \t\tif((Arg1::name() != arg1.first) || \t\t\t(Arg2::name() != arg2.first) || \t\t\t(Arg3::name() != arg3.first)) \t\t{ #if defined(DEBUG) \t\t\t::OutputDebugStringW(Sprintf&lt;wchar_t&gt;( \t\t\t\tL&quot;Function: \\&quot;%s\\&quot;:\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot;, \t\t\t\tdbg_function_name.c_str(), \t\t\t\tArg1::name().c_str(), arg1.first.c_str(), \t\t\t\tArg2::name().c_str(), arg2.first.c_str(), \t\t\t\tArg3::name().c_str(), arg3.first.c_str()).c_str()); #endif \t\t\tASSERT_MESSAGE_AND_RETURN_VALUE(false, &quot;Type mismatch&quot;, false); \t\t} \t\t\/\/ Call function with 3 args \t\tf(Arg1::convert(arg1.second), \t\t\tArg2::convert(arg2.second), \t\t\tArg3::convert(arg3.second)); \t\treturn true; \t} };  template&lt;&gt; struct FunctionCaller&lt;4&gt; { \ttemplate&lt;typename Function&gt; \tstatic bool call(Function f, const InvokeParser::ArgsContainer& args #if defined(DEBUG) \t\t, const std::wstring& dbg_function_name #endif \t\t) \t{ \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg1_type&gt; Arg1; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg2_type&gt; Arg2; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg3_type&gt; Arg3; \t\ttypedef FlashType&lt;typename boost::function_traits&lt;Function&gt;::arg4_type&gt; Arg4;  \t\tconst InvokeParser::TypeValuePair& arg1 = args[0]; \t\tconst InvokeParser::TypeValuePair& arg2 = args[1]; \t\tconst InvokeParser::TypeValuePair& arg3 = args[2]; \t\tconst InvokeParser::TypeValuePair& arg4 = args[3];  \t\tif((Arg1::name() != arg1.first) || \t\t\t(Arg2::name() != arg2.first) || \t\t\t(Arg3::name() != arg3.first) || \t\t\t(Arg4::name() != arg4.first)) \t\t{ #if defined(DEBUG) \t\t\t::OutputDebugStringW(Sprintf&lt;wchar_t&gt;( \t\t\t\tL&quot;Function: \\&quot;%s\\&quot;:\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot; \t\t\t\tL&quot;%s -&gt; %s\\n&quot;, \t\t\t\tdbg_function_name.c_str(), \t\t\t\tArg1::name().c_str(), arg1.first.c_str(), \t\t\t\tArg2::name().c_str(), arg2.first.c_str(), \t\t\t\tArg3::name().c_str(), arg3.first.c_str(), \t\t\t\tArg4::name().c_str(), arg4.first.c_str()).c_str()); #endif \t\t\tASSERT_MESSAGE_AND_RETURN_VALUE(false, &quot;Type mismatch&quot;, false); \t\t} \t\t\/\/ Call function with 4 args \t\tf(Arg1::convert(arg1.second), \t\t\tArg2::convert(arg2.second), \t\t\tArg3::convert(arg3.second), \t\t\tArg4::convert(arg4.second)); \t\treturn true; \t} }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 \u0441\u0430\u043c <code>Function<\/code>:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Function<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">struct IFunction { \tvirtual bool call(const InvokeParser& parser) = 0;  \tvirtual ~IFunction() \t{ \t} };  template&lt;typename FunctionPointer&gt; struct Function : \tpublic IFunction { \tFunction(const std::wstring& function_name, FunctionPointer f) \t\t: f_(f) \t\t, name_(function_name) \t{ \t} \t \tbool call(const InvokeParser& parser) \t{ \t\ttypedef typename boost::remove_pointer&lt;FunctionPointer&gt;::type FunctionType; \t\tenum { ArgsCount = boost::function_traits&lt;FunctionType&gt;::arity };  \t\tASSERT_MESSAGE_AND_RETURN_VALUE( \t\t\tname_ == parser.function_name(), \t\t\t&quot;Incorrect function name&quot;, \t\t\tfalse);  \t\tASSERT_MESSAGE_AND_RETURN_VALUE( \t\t\tArgsCount == parser.arguments_count(), \t\t\t&quot;Incorrect function arguments count&quot;, \t\t\tfalse);  \t\treturn FunctionCaller&lt;ArgsCount&gt;::template call&lt;FunctionType&gt;( \t\t\tf_, parser.arguments() #if defined(DEBUG) \t\t\t, name_ #endif \t\t\t); \t}  protected: \tFunctionPointer f_; \tstd::wstring name_; };  template&lt;typename FunctionPointer&gt; IFunction* CreateFunction(const std::wstring& name, FunctionPointer f) { \treturn new Function&lt;FunctionPointer&gt;(name, f); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!      \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/223865\/\"> http:\/\/habrahabr.ru\/post\/223865\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">     \t\u041f\u0440\u0438\u0432\u0435\u0442!<br \/>  \u041d\u0435 \u0437\u043d\u0430\u043b, \u043a\u0430\u043a \u043f\u043e\u0442\u043e\u0447\u043d\u0435\u0435 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0432\u0443\u0447\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<blockquote><p>\u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u0442\u0440\u043e\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0438\u043c\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0435\u0451 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u041d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.<\/p><\/blockquote>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a <a href=\"http:\/\/help.adobe.com\/en_US\/ActionScript\/3.0_ProgrammingAS3\/WS5b3ccc516d4fbf351e63e3d118a9b90204-7caf.html\">ActionScript<\/a> \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <u>test<\/u> \u0441 \u0442\u0440\u0435\u043c\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 <i>str<\/i>, <i>false<\/i>, <i>1.0<\/i>(\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432: <i>String<\/i>, <i>Boolean<\/i>, <i>Number<\/i>):  <\/p>\n<pre><code class=\"xml\">&lt;invoke name=&quot;test&quot; returntype=&quot;xml&quot;&gt;&lt;arguments&gt;&lt;string&gt;str&lt;\/string&gt;&lt;false\/&gt;&lt;number&gt;1.0&lt;\/number&gt;&lt;\/arguments&gt;&lt;\/invoke&gt; <\/code><\/pre>\n<p>  \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b C++ \u0431\u044b\u043b\u0430 \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:  <\/p>\n<pre><code class=\"cpp\">void test_handler(const std::wstring&#038; str, bool flag, double n); <\/code><\/pre>\n<p>  \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 \u0438, \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430(\u0438 \u043a\u0430\u043f\u0435\u043b\u044c\u043a\u0438 boost-\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-223865","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/223865","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=223865"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/223865\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=223865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=223865"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=223865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}