{"id":327934,"date":"2022-01-13T15:00:12","date_gmt":"2022-01-13T15:00:12","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=327934"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=327934","title":{"rendered":"<span>\u041e \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u0432 \u0421++, \u0447\u0443\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/146\/afb\/653\/146afb65362095046986be80593f7dd1.JPG\" width=\"1600\" height=\"757\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e <a href=\"https:\/\/habr.com\/ru\/post\/599801\/\" rel=\"noopener noreferrer nofollow\">\u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u0421++ \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445<\/a> \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0436\u0433\u0443\u0447\u0435\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435  \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u0445\u043e\u0436\u0435\u0435, \u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0434\u0430 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u0431\u044b\u043b \u043d\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u043c, \u0438 \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0443\u0447\u043d\u043e \u043d\u0435 \u0431\u044b\u043b\u043e. \u0410 \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u0447\u0435\u0433\u043e \u0431\u044b \u0442\u043e \u043d\u0438 \u0431\u044b\u043b\u043e \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0442\u043e \u044d\u0442\u0438\u043c \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u044b.  <\/p>\n<h3>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#problem\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#start\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#simple\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#overloading\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sfinae_pt1\" rel=\"noopener noreferrer nofollow\">SFINAE (Substitution Failure Is Not An Error) &#8212; \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u0442\u043e \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0433\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sfinae_pt2\" rel=\"noopener noreferrer nofollow\">SFINAE \u0438 trailing return type<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#collections\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c makeString() \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#strings\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c makeString() \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#traits\" rel=\"noopener noreferrer nofollow\">Type traits &#8212; \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0438\u043f\u043e\u0432 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043f\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u043c\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 (by Non-type template parameter)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#cppinsight\" rel=\"noopener noreferrer nofollow\">\u0427\u0442\u043e \u0436\u0435 \u0442\u044b, ____ [\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440], \u0434\u0435\u043b\u0430\u0435\u0448\u044c&#8230; <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#std_type_traits\" rel=\"noopener noreferrer nofollow\">\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 type_traits <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#perfect_forwarding\" rel=\"noopener noreferrer nofollow\">\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 std::forward<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_pt1\" rel=\"noopener noreferrer nofollow\">Variadic templates &#8212; \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_recursion\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a variadic templates<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_fold\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0445\u043e\u0434 \u0441\u043e \u0441\u0432\u0435\u0440\u0442\u043a\u043e\u0439 (fold expression) \u043a Variadic templates<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#concepts\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f (constraints) &#8212; \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0430\u0445\u0430\u0440 \u0434\u043b\u044f SFINAE<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"http:\/\/why_better\" rel=\"noopener noreferrer nofollow\">\u0421\u0442\u0430\u043b\u043e \u043b\u0438 \u0441 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430\u043c\u0438 \u043b\u0443\u0447\u0448\u0435?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#results\" rel=\"noopener noreferrer nofollow\">\u0418\u0442\u043e\u0433\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"problem\" id=\"problem\"><\/a><\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h3>\n<p>\u0412 \u0438\u043c\u0435\u044e\u0449\u0435\u043c\u0441\u044f <code>std::to_string<\/code> \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u043a\u043e\u0432: <\/p>\n<ul>\n<li>\n<p>\u043e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0435 \u043d\u0430\u043c\u0438. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0435\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u043f\u044b\u0442 \u0438 \u043c\u043e\u0440\u0435 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u043a\u0435\u043c-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u043c.<\/p>\n<\/li>\n<li>\n<p>\u043e\u043d \u043d\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e <code>std<\/code> \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0438 \u0434\u0430\u0436\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/extending_std\" rel=\"noopener noreferrer nofollow\">\u043e \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/a>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0436\u0430\u0440\u043a\u0438\u0435 \u0441\u043f\u043e\u0440\u044b \u0432 \u043a\u0443\u0440\u0438\u043b\u043a\u0435. <\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <code>makeString<\/code> \u0441 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043e\u0442 <code>std::to_string<\/code> \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430\u043c\u0438. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043a \u043d\u0435\u043c\u0443 \u0431\u0443\u0434\u0443\u0442:<\/p>\n<ul>\n<li>\n<p>\u0441\u0445\u043e\u0436\u0438\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441: <code>makeString(3.14);<\/code> \u0438 <code>makeString(directionVector);<\/code> \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437 \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u044c. \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u044c\u043b\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430  <code>class UserRequest;<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>std::string to_string() const;<\/code> \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u043d\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434 <code>to_string<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u0434 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0421++ \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c &#171;\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187; \u0432 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 Ubuntu 20.04.3 LTS \u0438\u043b\u0438 VS 2019 Community Edition. \u0410 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0431\u044b\u043b \u0447\u0438\u0441\u0442\u044b\u0439 C++, \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0431\u044b\u0442\u044c \u0441 \u043d\u0430\u043c\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0436\u0435. \u042f \u043f\u0435\u0440\u0435\u0434\u0430\u043c \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0441\u044c\u0431\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CMake-\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0438 \u0431\u0443\u0434\u0443 \u043d\u0430\u0434\u0435\u044f\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0443 \u0421++ \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432 \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u044d\u0442\u0438 \u0440\u0443\u043d\u044b \u0432 \u0441\u0432\u043e\u044e \u043b\u044e\u0431\u0438\u043c\u0443\u044e IDE \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u043b\u044e\u0431\u0438\u043c\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430. <\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cmake\">cmake_minimum_required(VERSION 3.0.0) project(makeString VERSION 0.1.0)  add_executable(makeString main.cpp)  set(CMAKE_CXX_EXTENSIONS OFF)      # no vendor-specific extensions set_property(TARGET makeString PROPERTY CXX_STANDARD 20)  if (MSVC)     target_compile_options(makeString PUBLIC \/W4 \/WX \/Za \/permissive-) else()     target_compile_options(makeString PUBLIC -Wall -Wextra -pedantic -Werror) endif()<\/code><\/pre>\n<h3>\u041e\u043f\u044b\u0442 \u0438 \u043c\u043e\u0440\u0435 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f<\/h3>\n<p><a class=\"anchor\" name=\"start\" id=\"start\"><\/a><\/p>\n<p>\u0418 \u0442\u0430\u043a, \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 \u0421++:<\/p>\n<pre><code class=\"cpp\">#include &lt;iostream> #include \"makeString.hpp\"  struct A {     std::string to_string() const { return \"A\"; } };  struct B {     int m_i = 0;     std::string to_string() const { return \"B{\" + std::to_string(m_i) + \"}\"; } };  int main() {     A a;     B b = {1};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b); }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"simple\" id=\"simple\"><\/a><\/p>\n<h4>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/h4>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b <code>to_string<\/code> \u0443 \u043d\u0430\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043a\u0441\u043a\u0438 &#171;\u043f\u043e\u0434\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u043b\u0441\u044f&#187; \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0448\u0430\u0431\u043b\u043e\u043d. \u0428\u0430\u0431\u043b\u043e\u043d &#8212; \u044d\u0442\u043e \u0432\u0435\u0449\u044c, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435\u0445\u0438\u0442\u0440\u0430\u044f, \u043d\u043e \u0435\u0441\u043b\u0438 \u0443\u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/599801\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0433\u0434\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043e\u0441\u043d\u043e\u0432\u044b. <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0440\u0430\u043b\u0438, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442: <code>a: A; b: B{1}<\/code><\/p>\n<p><a class=\"anchor\" name=\"overloading\" id=\"overloading\"><\/a><\/p>\n<h4>\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h4>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>makeString(3.14)<\/code> \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0443 \u0442\u0438\u043f\u0430 <code>double<\/code> \u043d\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 <code>to_string<\/code>. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>std::to_string<\/code> \u0443 \u043d\u0430\u0441 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u0431\u0438\u0440\u0430\u043b, \u0438 \u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u043f\u0440\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. <\/p>\n<pre><code class=\"cpp\">int main() {   \/\/ ...      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14)               &lt;&lt; std::endl; }<\/code><\/pre>\n<pre><code class=\"cpp\">\/\/ makeString.hpp ... \/\/ [build] ..\/makeString.hpp:13:24: error:  \/\/ template-id \u2018makeString&lt;>\u2019 for \u2018std::string makeString(double)\u2019  \/\/ does not match any template declaration template &lt;> std::string makeString(double d) { return std::to_string(d); }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u0438\u043d &#8212; \u043a\u043e\u043c\u043e\u043c. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043e\u0439. \u041e\u0441\u0432\u0435\u0436\u0438\u0432 \u0441\u0432\u043e\u0438 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/template_specialization\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u043d\u0430 cppreference<\/a>, \u043c\u044b \u0435\u043c\u0443 \u043f\u043e\u043c\u043e\u0436\u0435\u043c, \u0438 \u043f\u043e\u043d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e <a href=\"https:\/\/godbolt.org\/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGEgJykrgAyeAyYAHI%2BAEaYxBIapAAOqAqETgwe3r4ByanpAqHhUSyx8VyJdpgOGUIETMQEWT5%2BXIFVNQJ1DQRFkTFxCbb1jc05bcM9fSVlCQCUtqhexMjsHASYLEkGGwDUJgDMbgQAnkmMrJi7ACqH2CYaAIKYqhvEDLsAbqh46LvosgA8klHCw8AAvTCArwECDXOaHKxPB6PDZbHZXQ7HM4XNg3O77J7fX67fioCBoBgKAj4swANl2qGi2mqBDm%2BwA7BZ\/kCQXgwZDobCmSyHAiDlYOQARFEotHbJh7LEElHEv5kikCam7MIEcwMvDskxcnmCYGgiFQmEQQ2I40y5FPanELwOXYADU5Fl1Ort0rtjsePpYTDCNsEuwawGQpF2yAQDQAVJHiMBPiYAKxWDNShHIrko3ZFj3F1Rerj2gOPYs6iN4fYHKW7MxVwvFjWqcVI6vt1Dk20S2XSjgLWicDO8PwcLSkVCcNzWay7BRLFaYswHHikAiaEcLADWIEkHIAdJJJAAODRcDNcMxmC8cg4HaRjjiSSe72ecXgKECJHdpxHUg4FgGBEBQVAtjoOJyEoNBoPoeJgAUZgkgUBBUAIPg6DeP8IGiL9ojCBoTk4LcELYM0GFoMigNILAQyMcR6PwYhWTwT5MD\/eiXmqGE1hnXVMDfGdaDwaJiFIjwsC\/AhiH5cjgKoAwUIANTwTAAHdgUYJSZEEEQxHYKQDPkJQ1C\/XQuH0QxjEXSx9Akv9IAWVA%2BS1TgAFpATMX8RI45wIFcMZWiCBh0GmAZyjyNJHAEUK9BSOKMii0pBhsjp4oYbpRk8Fo9Cy2oRl6MJ%2BnSmLqR6RLMpKtLZi4BYV2WVY9HkzA1h4Udx0\/ei5w4VQLzpLy6UkXZo2QXYIHkrwGH3dkIAXSxrFjXBCBIfYNxs3YPEQuJNs3OZeEArQFggJAEKSGCyAoTU9viZADCMAB9Ga5pw2g8MoQj6OI5hiDoiioKoghARouiZ0YuyWMhvB2JqLieJnPjkAEr9hNE3hxMk6SMEE46FJYJSFhUph1M0nTzinLd%2BEM0RxFM2nzJUdR6N0MxbKMFAHJsbGXIgNyPKpbzfP8%2BxspcCKavCyKypmDLYoKTJ8vGRXsvqhWiq6Erpa1nK6rl6LCp1lWwqqxoNfKJrV1amz2s64C3wnUgpxnfrBuG0a4ye4Apre%2BapqWqxHN2NaiGIA7tt2q6kIOswju3Xc5gPEAM0SN8P1IImOS4E8uA5HP88LguuHzl2v3639\/0ToCzvA86QCWAgkhhOC7pjhXMHwcO9CZoyGekJnFBZuT2Id0gtKkpJif0Hry76zghRbmlUCoXYPZGsaJr9l05oW6PrsjhOTr3UgEEwJgsHiAXZ\/fXgiYfE8L3vC9n4fN\/X\/pee3Z\/Wxq5P5OpBDwZjMCeDMt5\/AXkvCXekdI6S3wOL1H%2BHBjpJ26hwPy39eCVxrqdBYXFiBpGcJIIAA%3D%3D\" rel=\"noopener noreferrer nofollow\">\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 &#171;\u043f\u043e\u0434\u0447\u0438\u0441\u0442\u0438\u0442&#187;<\/a> \u0437\u0430 \u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435. \u0422\u0430\u043a \u0436\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u043a\u0440\u043e\u043c\u0435 <code>double<\/code> \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>float<\/code> \u0438  \u0435\u0449\u0435 7 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 <code>std::to_string<\/code>:<\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object &amp;object) {     return object.to_string(); }  template &lt;> std::string makeString(const double&amp; d) { return std::to_string(d); } template &lt;> std::string makeString(const float&amp; f)  { return std::to_string(f); } template &lt;> std::string makeString(const int&amp; i)    { return std::to_string(i); } \/\/ ... 6 more specializations ...<\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c, \u043e\u0434\u043d\u0430\u043a\u043e, \u0438 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043d\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. \u041a\u0440\u0430\u0435\u043c \u0433\u043b\u0430\u0437\u0430 \u0433\u043b\u044f\u043d\u0443\u0432 \u0440\u0430\u0437\u0434\u0435\u043b <em>Function template overloading<\/em> \u0432 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/function_template\" rel=\"noopener noreferrer nofollow\">\u0441\u0430\u0439\u0442\u0435<\/a>, \u0438\u043c\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0442.\u043a. \u043e\u043d\u0438 \u043d\u0435 \u043f\u043b\u0430\u0442\u044f\u0442 \u043c\u043d\u0435 \u0437\u0430 SEO. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u0430, \u043c\u043e\u0436\u043d\u043e \u043f\u043b\u043e\u0434\u043e\u0442\u0432\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0437\u0430 \u0435\u0451 \u0447\u0442\u0435\u043d\u0438\u0435\u043c \u043d\u0435 \u043e\u0434\u043d\u0438 \u0441\u0443\u0442\u043a\u0438. <\/p>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0433\u0434\u0430, \u0431\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434. \u041f\u043e\u0434\u0445\u043e\u0434 \u0441 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439, \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439, \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0435\u0435 \u043f\u0430\u0447\u043a\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. <\/p>\n<pre><code class=\"cpp\">\/\/ overloading instead of specializations std::string makeString(double d) { return std::to_string(d); } std::string makeString(float f)  { return std::to_string(f); } std::string makeString(int i)    { return std::to_string(i); } \/\/ ... 6 more overloads ...<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u043a\u0441\u043a\u0430\u0435\u043c, \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e: <code>a: A; b: B{1}; pi: 3.140000<\/code><\/p>\n<p>\u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u044b \u0438\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u043c\u044b\u0441\u043b\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0443 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0451 \u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0448\u0430\u0431\u043b\u043e\u043d. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }  \/*   [build] ..\/main.cpp: In function \u2018int main()\u2019:   [build] ..\/main.cpp:20:39: error: call of overloaded \u2018makeString(A&amp;)\u2019 is ambiguous   [build]    20 |     std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b) *\/ template &lt;typename Numeric> std::string makeString(Numeric value) {     return std::to_string(value); } <\/code><\/pre>\n<p>\u0418 \u0432\u0435\u0434\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e: \u0435\u0441\u0442\u044c \u0432\u044b\u0437\u043e\u0432 <code>makeString(a)<\/code>, \u0433\u0434\u0435 <code>a<\/code> \u0432 \u043c\u0435\u0441\u0442\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f  <code>A&amp;<\/code> (<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/value_category\" rel=\"noopener noreferrer nofollow\">lvalue reference to A<\/a>), \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u043c\u0443 \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043d\u0430\u0434\u043e \u044d\u0442\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u0442.\u043a. \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0435\u0440\u043d\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 \u043e\u0431\u0430 <em>\u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f (declaration)<\/em> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0432 <em>\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 (definition)<\/em> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u043d \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043b\u0435\u0437\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435 &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c&#187; \u043e\u0434\u043d\u0443 \u0438\u0437 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440 \u0438\u0437 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. \u0416\u0435\u043b\u0430\u043d\u0438\u0435 \u0435\u0441\u0442\u044c, \u0432 \u043d\u043e\u0440\u043c\u044b \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u043e\u0440\u0430\u043b\u0438 \u043e\u043d\u043e \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0435\u043c\u0443 \u043f\u0440\u043e\u0442\u0438\u0432\u0438\u0442\u044c\u0441\u044f, \u0432\u0435\u0434\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c&#8230;<\/p>\n<p><a class=\"anchor\" name=\"sfinae_pt1\" id=\"sfinae_pt1\"><\/a><\/p>\n<h4>SFINAE (Substitution Failure Is Not An Error) &#8212; \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u0442\u043e \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0433\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/h4>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0443 \u043d\u0438\u0445 (\u0443 \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u043f\u043b\u0430\u0442\u0438\u0442 \u043c\u043d\u0435 \u0437\u0430 SEO), <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/sfinae\" rel=\"noopener noreferrer nofollow\">SFINAE \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c<\/a>. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043d\u0435 \u0447\u0438\u0442\u0430\u0442\u044c, \u0430 \u043f\u0438\u0441\u0430\u0442\u044c: \u0435\u0441\u043b\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <strong><em>\u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445<\/em><\/strong> \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 <strong><em>\u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435<\/em><\/strong> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f, \u0442\u043e \u044d\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0431\u0435\u0437 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e \u0438 \u0434\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. <\/p>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c&#187; \u043e\u0434\u0438\u043d \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0438\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438, \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0430\u043c\u043e\u0439&#187; \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043c\u0435\u0441\u0442\u0435 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0430. \u041f\u0440\u043e\u044f\u0432\u0438\u0432 \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u044e, \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c \u0438 \u0441\u043c\u0435\u043a\u0430\u043b\u043a\u0443, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0439\u0442\u0438 \u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;utility>  \/\/ for std::declval  \/\/ (1) template &lt;typename Object,            typename = decltype(std::declval&lt;Object>().to_string())> std::string makeString(const Object&amp; object) {     return object.to_string(); }  namespace Impl { bool acceptNumber(int); }  \/\/ (2) template &lt;typename Numeric> std::string makeString(Numeric value,                         decltype(Impl::acceptNumber(value))* = nullptr) {     return std::to_string(value); }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0440\u0443\u043d\u044b: <\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430: \u0442\u0438\u043f \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0438 \u0431\u0435\u0437\u044b\u043c\u044f\u043d\u044b\u0439 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u043e\u0433\u043e \u0436\u0435 \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <code>Object::to_string()<\/code> \u0434\u043b\u044f \u0441\u0444\u0435\u0440\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>Object<\/code> \u0432 \u0432\u0430\u043a\u0443\u0443\u043c\u0435. <code>std::declval&lt;Object><\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0430 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0442.\u043a. \u0443 \u0442\u0438\u043f\u0430 Object \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0431\u044b\u0442\u044c. <\/p>\n<p>\u0414\u043b\u044f \u0442\u0438\u043f\u043e\u0432 <code>A<\/code> \u0438 <code>B<\/code> \u0434\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>makeString<\/code>, \u043d\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0442\u0438\u043f\u0430 <code>double<\/code>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0442\u0438\u043f <code>std::declval&lt;double>().to_string()<\/code> \u0438 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u043e\u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435. <\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445 &#8212; \u044d\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <code>Impl::acceptNumber(value)<\/code>, \u0430 \u0442\u0430\u043a, \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 <code>acceptNumber<\/code> \u043e\u0431\u044c\u044f\u0432\u043b\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f int \u0438 \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043d\u0435\u044f\u0432\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c\u044b\u0445 \u043a \u043d\u0435\u043c\u0443, \u0442\u043e \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u043e\u0434\u0441\u0442\u0432\u0430\u0438\u0442\u044c \u0442\u0443\u0434\u0430 <code>struct A<\/code> \u0438\u043b\u0438 <code>struct B<\/code> \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0442\u0441\u044f \u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e. <code>double<\/code> \u0436\u0435 \u043d\u0435\u044f\u0432\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442\u0441\u044f \u043a <code>int<\/code>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0442\u0438\u043f <code>decltype(Impl::acceptNumber(value))<\/code> \u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<\/li>\n<\/ol>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c, \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e. <\/p>\n<p><a class=\"anchor\" name=\"sfinae_pt2\" id=\"sfinae_pt2\"><\/a><\/p>\n<h4>SFINAE \u0438 Trailing return type<\/h4>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u044b\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c-\u043f\u0443\u0441\u0442\u044b\u0448\u043a\u0430\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0438 \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <code>auto<\/code> \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u044f\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u043e \u0438\u0437 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432 \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u043d\u0438 \u043c\u0435\u0442\u043e\u0434\u0443 \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u044f\u0432\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u041a \u0441\u043b\u043e\u0432\u0443, \u044d\u0442\u043e \u043c\u043e\u0439 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SFINAE \u0431\u0435\u0437 \u0441\u043c\u0441 \u0438 type_traits \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0421++17: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  \/\/ (3) template &lt;typename Object> auto makeString(const Object &amp;object) -> decltype(object.to_string()) {     return object.to_string(); }  \/\/ (4) template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }<\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 <code>auto<\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0430 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u0432\u0438\u0434\u0430 <code>-> decltype(...)<\/code>\u043d\u0435 \u0434\u0430\u0441\u0442 \u0435\u043c\u0443 \u044d\u0442\u043e\u0433\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0441\u043b\u0438:<\/p>\n<ol start=\"3\">\n<li>\n<p>\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 <code>object.to_string()<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 <code>std::to_string(object)<\/code>;<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u043c, \u043e\u043d \u0447\u0438\u0442\u0430\u0435\u043c, \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0430\u0435\u043c, \u043d\u043e \u0435\u0433\u043e \u043c\u0430\u043b\u043e. 17 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u043d\u0430 \u043e\u0434\u043d\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u043f\u043e\u0440\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0435\u0449\u0435 \u043e\u0434\u043d\u0438\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c: \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043d\u043e \u0438 \u0438\u0437 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439.<\/p>\n<p><a class=\"anchor\" name=\"collections\" id=\"collections\"><\/a><\/p>\n<h4> \u041f\u0438\u0448\u0435\u043c makeString() \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439  <\/h4>\n<p>\u0418\u0442\u0430\u043a, \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u0437\u0430\u0434\u0430\u0447\u0443: <\/p>\n<pre><code class=\"cpp\">    \/\/ ...      const std::vector&lt;int> xs = {1, 2, 3};     const std::set&lt;float> ys = {4, 5, 6};     const double zs[] = {7, 8, 9};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14) &lt;&lt; std::endl               &lt;&lt; \"xs: \" &lt;&lt; makeString(xs) &lt;&lt; \"; ys: \" &lt;&lt; makeString(ys)                &lt;&lt; \"; zs: \" &lt;&lt; makeString(zs)               &lt;&lt; std::endl;<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430\u0431\u043e\u0442\u043b\u0438\u0432\u043e \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u043d\u0430\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e <code>no matching function for call to \u2018makeString(const std::vector&lt;int>&amp;)\u2019<\/code>, \u0442.\u043a. \u043e\u0431\u0430 \u0438\u043c\u0435\u044e\u0449\u0438\u0445\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0440\u0435\u0442\u0438\u0439. <\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0437\u0430\u0434\u0430\u0447\u0435\u0439: \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u0430: <code>vector<\/code>, <code>set<\/code>, <code>double[]<\/code>. \u041c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u043e\u0431\u0449\u0435\u0435. <\/p>\n<p>\u0421 \u043c\u043e\u0435\u0439 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f, \u043f\u043e \u0432\u0441\u0435\u043c \u0442\u0440\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0412\u043e\u043e\u0440\u0443\u0436\u0438\u043c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>std::begin()<\/code> \u0438 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u043d\u0438\u044f\u043c\u0438 \u043e SFINAE, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 <code>makeString.hpp<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u0443\u0436\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <code>makeString<\/code> \u0434\u043b\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0440\u0430\u0437\u044b\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430 <code>std::begin<\/code> \u0434\u043b\u044f \u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"cpp\">template &lt;typename Iterable> auto makeString(const Iterable&amp; iterable)      -> decltype(makeString(*std::begin(iterable))) { std::string result; for (const auto&amp; i : iterable) { if (!result.empty()) result += ';'; result += makeString(i); }  return result; }<\/code><\/pre>\n<p>\u0421\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c, \u0432\u043e\u0437\u0440\u0430\u0434\u0443\u0435\u043c\u0441\u044f:<\/p>\n<pre><code class=\"cpp\">a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0432\u044b\u0448\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0432\u0430\u043c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0439, \u043d\u0435 \u0440\u0430\u0441\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c: \u043f\u043e\u0445\u043e\u0436\u0435, \u0443 \u0432\u0430\u0441 \u0435\u0449\u0435 \u043d\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0444\u0434\u0435\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u0410 \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u043d\u0435 \u0440\u0430\u0441\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c, \u043d\u043e \u043f\u0440\u043e\u0444\u0434\u0435\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0443\u0436\u0435 \u0435\u0441\u0442\u044c.<\/p>\n<p><a class=\"anchor\" name=\"strings\" id=\"strings\"><\/a><\/p>\n<h4> \u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c makeString() \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a<\/h4>\n<p>\u0420\u0430\u0437 \u0443\u0436 \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c <code>std::string<\/code> \u0438\u0437 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0445\u043d\u044b\u0445 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437 \u0421-\u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. <\/p>\n<p>\u0414\u043e\u043f\u0438\u0448\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 <code>int main()<\/code> \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">int main() {     A a;     B b = {1};      const std::vector&lt;int> xs = {1, 2, 3};     const std::set&lt;float> ys = {4, 5, 6};     const double zs[] = {7, 8, 9};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14) &lt;&lt; std::endl               &lt;&lt; \"xs: \" &lt;&lt; makeString(xs) &lt;&lt; \"; ys: \" &lt;&lt; makeString(ys)                &lt;&lt; \"; zs: \" &lt;&lt; makeString(zs)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"Hello, \")                &lt;&lt; makeString(std::string_view(\"world\"))                &lt;&lt; makeString(std::string(\"!!1\"))                &lt;&lt; std::endl; }<\/code><\/pre>\n<p>\u0421\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442! \u041d\u043e \u043d\u0435 \u0442\u0430\u043a, \u043a\u0430\u043a \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b: <\/p>\n<pre><code class=\"cpp\">a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 72;101;108;108;111;44;32;0119;111;114;108;10033;33;49<\/code><\/pre>\n<p>\u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434 <code>makeString(const Iterable&amp; iterable)<\/code>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0442\u0438\u043f <code>char<\/code> &#8212; \u0446\u0435\u043b\u044b\u0439, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>std::to_string(char)<\/code>  \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043d\u0435\u0442, \u0430 \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u043c\u044b \u0432\u0441\u0435 \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0447\u0438\u0442\u0430\u043b\u0438 \u0432 \u0440\u0430\u0437\u0434\u0435\u0440\u0435 <em>Integer promotions<\/em> <a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/conversion\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c \u0441\u0430\u0439\u0442\u0435<\/a>, <code>char<\/code> &#171;\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435&#187; \u0434\u043e <code>int<\/code> \u0438 \u043d\u0430\u0448 \u043a\u043e\u0434 \u0440\u0430\u0434\u043e\u0441\u0442\u043d\u043e \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0442\u0440\u0438 \u043f\u0430\u0447\u043a\u0438 \u0446\u0435\u043b\u044b\u0445 \u0447\u0438\u0441\u0435\u043b \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a. <\/p>\n<p><a class=\"anchor\" name=\"traits\" id=\"traits\"><\/a><\/p>\n<h4>Type traits &#8212; \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0438\u043f\u043e\u0432 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043f\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u043c\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 (by Non-type template parameter)<\/h4>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 <code>makeString(const Iterable&amp; iterable)<\/code>\u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0438 \u0434\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a. \u0417\u0430\u0434\u0430\u0447\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0442\u0438\u043f\u0430 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0443\u0436\u0435 \u0440\u0435\u0448\u0430\u043b\u0430\u0441\u044c \u0434\u043e \u043d\u0430\u0441, \u0438 \u0432 \u043e\u0431\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u043e\u043d\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;type traits&#187;. <\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u043d\u0438\u0447\u0442\u043e \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u0440\u043e\u043c\u0435 <code>std::string, std::string_view<\/code> \u0438 <code>char*<\/code>. \u0412\u044b\u0440\u0430\u0437\u0438\u043c \u044d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0421++ \u043a\u043e\u0434:<\/p>\n<pre><code class=\"cpp\">namespace Impl { template &lt;typename NotString> inline constexpr bool isString  = false; template &lt;> inline constexpr bool isString&lt;std::string>       = true; template &lt;> inline constexpr bool isString&lt;char*>             = true; template &lt;> inline constexpr bool isString&lt;const char*>       = true; template &lt;> inline constexpr bool isString&lt;const char* const> = true; template &lt;> inline constexpr bool isString&lt;std::string_view>  = true; }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c <code>Imlp::isString&lt;T><\/code> \u0431\u0443\u0434\u0435\u0442 <code>false<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043a\u0440\u043e\u043c\u0435 \u0442\u0435\u0445, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f <code>true<\/code>. \u0414\u0435\u043b\u043e \u0437\u0430 \u043c\u0430\u043b\u044b\u043c: \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 <code>makeString(const Iterable&amp; iterable)<\/code>\u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0430 \u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043a\u043e\u0433\u0434\u0430 <code>IsString&lt;Iterable> == true<\/code>. <\/p>\n<p>\u0412\u0441\u043f\u043e\u043c\u043d\u0438\u0432, \u0447\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f, \u043d\u043e \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>bool<\/code>, \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043e\u0431\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u044b\u043c, \u0430 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f <code>true<\/code> \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440:<\/p>\n<pre><code class=\"cpp\">template &lt;bool B, class T = void> struct enable_if; template &lt;class T> struct enable_if&lt;true, T> { using type = T; }; \/\/ syntax sugar: 'enable_if_v' is equivalent of 'typename enable_if&lt;B,T>::type' template &lt;bool B, class T> using enable_if_t = typename enable_if&lt;B,T>::type;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 <code>enable_if&lt;true, T>::type<\/code> \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u043a\u0430\u043a <code>enable_if&lt;false, T>::type<\/code>\u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d, \u0438 \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 (\u0447\u0442\u043e, \u043a\u0430\u043a \u043d\u0430\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, &#171;is not an error&#187;). \u0427\u0442\u043e\u0431\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c, \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c <code>enable_if_t<\/code>. <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u043e\u0431\u044c\u044f\u0441\u043d\u044e \u043f\u0440\u0438\u0447\u0438\u043d\u0443: \u044f \u0435\u0433\u043e \u043d\u0435 \u043f\u0438\u0441\u0430\u043b \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0438\u043b \u0438\u0437 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/enable_if\" rel=\"noopener noreferrer nofollow\">\u043e\u0434\u043d\u043e\u0433\u043e \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430<\/a>. <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043e\u0434 \u0432 \u043a\u0443\u0447\u0443, \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043e\u0442 \u043f\u043b\u0430\u0433\u0438\u0430\u0442\u0430, \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits>  namespace Impl { template &lt;typename NotString> inline constexpr bool isString  = false; template &lt;> inline constexpr bool isString&lt;std::string>       = true; template &lt;> inline constexpr bool isString&lt;char*>             = true; template &lt;> inline constexpr bool isString&lt;const char*>       = true; template &lt;> inline constexpr bool isString&lt;const char* const> = true; template &lt;> inline constexpr bool isString&lt;std::string_view>  = true; }  template &lt;typename Object> auto makeString(const Object&amp; object) -> decltype(object.to_string()) {     return object.to_string(); }  template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }  template &lt;typename Iterable> auto makeString(const Iterable&amp; iterable)      -> std::enable_if_t&lt;!Impl::isString&lt;Iterable>,                          decltype(makeString(*std::begin(iterable)))> {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;typename String> auto makeString(const String&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(s); } <\/code><\/pre>\n<p>\u041a\u043e\u0434 \u0432\u0441\u0435 \u0435\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043a \u043b\u0443\u0447\u0448\u0435\u043c\u0443 \u0435\u0449\u0435 \u043d\u0435 \u0432\u0438\u0434\u043d\u043e \u043d\u0435\u0432\u043e\u043e\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u043c \u0433\u043b\u0430\u0437\u043e\u043c: \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u043b\u0438\u0442\u0435\u0440\u0430\u043b \u0432\u0441\u0451 \u0435\u0449\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u043c\u0430\u0441\u0441\u0438\u0432 \u0446\u0435\u043b\u044b\u0445. <\/p>\n<pre><code>a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 72;101;108;108;111;44;32;0world!!1<\/code><\/pre>\n<p><a class=\"anchor\" name=\"cppinsight\" id=\"cppinsight\"><\/a><\/p>\n<h4>\u0427\u0442\u043e \u0436\u0435 \u0442\u044b, ____ [\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440], \u0434\u0435\u043b\u0430\u0435\u0448\u044c&#8230; <\/h4>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c <a href=\"https:\/\/cppinsights.io\/lnk?code=Ly8gLS0tICNpbmNsdWRlICJtYWtlU3RyaW5nLmhwcCIgLS0tCiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCm5hbWVzcGFjZSBJbXBsCnsKdGVtcGxhdGUgPHR5cGVuYW1lIE5vdFN0cmluZz4gaW5saW5lIGNvbnN0ZXhwciBib29sIGlzU3RyaW5nICA9IGZhbHNlOwp0ZW1wbGF0ZSA8PiBpbmxpbmUgY29uc3RleHByIGJvb2wgaXNTdHJpbmc8c3RkOjpzdHJpbmc+ICAgICAgID0gdHJ1ZTsKdGVtcGxhdGUgPD4gaW5saW5lIGNvbnN0ZXhwciBib29sIGlzU3RyaW5nPGNoYXIqPiAgICAgICAgICAgICA9IHRydWU7CnRlbXBsYXRlIDw+IGlubGluZSBjb25zdGV4cHIgYm9vbCBpc1N0cmluZzxjb25zdCBjaGFyKj4gICAgICAgPSB0cnVlOwp0ZW1wbGF0ZSA8PiBpbmxpbmUgY29uc3RleHByIGJvb2wgaXNTdHJpbmc8Y29uc3QgY2hhciogY29uc3Q+ID0gdHJ1ZTsKdGVtcGxhdGUgPD4gaW5saW5lIGNvbnN0ZXhwciBib29sIGlzU3RyaW5nPHN0ZDo6c3RyaW5nX3ZpZXc+ICA9IHRydWU7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBPYmplY3Q+CmF1dG8gbWFrZVN0cmluZyhjb25zdCBPYmplY3QgJm9iamVjdCkgLT4gZGVjbHR5cGUob2JqZWN0LnRvX3N0cmluZygpKQp7CiAgICByZXR1cm4gb2JqZWN0LnRvX3N0cmluZygpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgTnVtZXJpYz4KYXV0byBtYWtlU3RyaW5nKE51bWVyaWMgdmFsdWUpIC0+IGRlY2x0eXBlKHN0ZDo6dG9fc3RyaW5nKHZhbHVlKSkKewogICAgcmV0dXJuIHN0ZDo6dG9fc3RyaW5nKHZhbHVlKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEl0ZXJhYmxlPgphdXRvIG1ha2VTdHJpbmcoY29uc3QgSXRlcmFibGUgJml0ZXJhYmxlKSAKICAgIC0+IHN0ZDo6ZW5hYmxlX2lmX3Q8IUltcGw6OmlzU3RyaW5nPEl0ZXJhYmxlPiwgZGVjbHR5cGUobWFrZVN0cmluZygqc3RkOjpiZWdpbihpdGVyYWJsZSkpKT4KewogICAgc3RkOjpzdHJpbmcgcmVzdWx0OwogICAgZm9yIChjb25zdCBhdXRvICZpIDogaXRlcmFibGUpCiAgICB7CiAgICAgICAgaWYgKCFyZXN1bHQuZW1wdHkoKSkKICAgICAgICAgICAgcmVzdWx0ICs9ICc7JzsKICAgICAgICByZXN1bHQgKz0gbWFrZVN0cmluZyhpKTsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0Owp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU3RyaW5nPgphdXRvIG1ha2VTdHJpbmcoY29uc3QgU3RyaW5nJiBzKQogICAgLT4gc3RkOjplbmFibGVfaWZfdDxJbXBsOjppc1N0cmluZzxTdHJpbmc+LCBzdGQ6OnN0cmluZz4KewogICAgcmV0dXJuIHN0ZDo6c3RyaW5nKHMpOwp9CgovLyAtLS0tLS0tLS0tLQoKLy8gbWFpbi5jcHAKCmV4dGVybiB2b2lkIGRvbnRPcHRpbWl6ZU91dChjb25zdCBzdGQ6OnN0cmluZyYpOwoKaW50IG1haW4oKQp7Cglkb250T3B0aW1pemVPdXQobWFrZVN0cmluZygiSGVsbG8sICIpKTsgCn0=&amp;insightsOptions=cpp2a&amp;std=cpp2a&amp;rev=1.0\" rel=\"noopener noreferrer nofollow\">\u0445\u043e\u0440\u043e\u0448\u043e \u043e\u0431\u0440\u0435\u0437\u0430\u043d\u043d\u044b\u0439 \u043a\u0443\u0441\u043e\u043a \u043a\u043e\u0434\u0430<\/a> \u043d\u0430 CppInsight, \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u044b\u0445\u043b\u043e\u043f. \u0414\u0435\u043b\u0430\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u044b:<\/p>\n<ul>\n<li>\n<p>\u0441\u0443\u0434\u044f \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435 #43 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 Insight, \u0448\u0430\u0431\u043b\u043e\u043d <code>auto makeString(Numeric value)<\/code> \u0440\u0430\u0441\u043a\u0440\u044b\u043b\u0441\u044f \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>char<\/code><\/p>\n<\/li>\n<li>\n<p>\u0430 \u0441\u0443\u0434\u044f \u043f\u043e #68, \u0448\u0430\u0431\u043b\u043e\u043d <code>auto makeString(const Iterable&amp; iterable)<\/code> \u0440\u0430\u0441\u043a\u0440\u044b\u043b\u0441\u044f \u0434\u043b\u044f \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0430 <code>\"Hello, \"<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f <code>char[8]<\/code>. <\/p>\n<\/li>\n<li>\n<p>\u043a \u0441\u043b\u043e\u0432\u0443, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430\u0431\u043e\u0442\u043b\u0438\u0432\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043b \u0434\u043b\u044f \u043d\u0430\u0441 <code>template&lt;><br \/> inline constexpr const bool isString&lt;char [8]> = false;<\/code> \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043d\u0443\u0436\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0447\u0442\u043e\u0431 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>Iterable-\u0432\u0435\u0440\u0441\u0438\u0438 makeString<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c, \u043f\u0440\u043e <em>Non-type template parameters,<\/em> \u0430 \u043f\u043e\u0442\u043e\u043c\u0443, \u043f\u043e \u043c\u043e\u0442\u0438\u0432\u0430\u043c \u0432\u044b\u0432\u043e\u0434\u0430 CppInsight \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u0418\u0442\u0430\u043a: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits>  namespace Impl { template &lt;typename NotString> inline constexpr bool isString  = false; template &lt;> inline constexpr bool isString&lt;std::string>       = true; template &lt;> inline constexpr bool isString&lt;char*>             = true; template &lt;> inline constexpr bool isString&lt;const char*>       = true; template &lt;> inline constexpr bool isString&lt;const char* const> = true; template &lt;> inline constexpr bool isString&lt;std::string_view>  = true;  template &lt;std::size_t N> inline constexpr bool isString&lt;char[N]> = true; }  template &lt;typename Object> auto makeString(const Object &amp;object) -> decltype(object.to_string()) {     return object.to_string(); }  template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }  template &lt;typename Iterable> auto makeString(const Iterable&amp; iterable)      -> std::enable_if_t&lt;!Impl::isString&lt;Iterable>,                          decltype(makeString(*std::begin(iterable)))> {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;typename String> auto makeString(const String&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(s); } <\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c:<\/p>\n<pre><code>a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 Hello, world!!1<\/code><\/pre>\n<p><a class=\"anchor\" name=\"std_type_traits\" id=\"std_type_traits\"><\/a><\/p>\n<h4>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 type_traits<\/h4>\n<p>\u041a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435\u043c, \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0433\u043b\u044f\u043d\u0443\u0442\u044c, \u0447\u0442\u043e \u0436\u0435 \u0435\u0449\u0435 \u0438\u043d\u0442\u0435\u0440\u0441\u043d\u043e\u0433\u043e \u0435\u0441\u0442\u044c <s>\u043d\u0430 cppreference<\/s> <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\" rel=\"noopener noreferrer nofollow\">\u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0434\u043b\u044f type_traits<\/a>. \u0410 \u0435\u0441\u0442\u044c \u0442\u0430\u043c, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, trait <code>std::is_convertible<\/code>, \u0447\u0442\u043e \u043d\u0430\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442 \u043d\u0430 \u0438\u0434\u0435\u044e \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u043e\u0432 \u0438 \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438. \u041f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 &#8212; \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0435\u044f\u0432\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 <code>std::string<\/code>. \u0410 \u043a\u043e\u0433\u0434\u0430 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e <code>std::string_view<\/code> \u043d\u0435 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 <code>std::string<\/code> \u043d\u0435\u044f\u0432\u043d\u043e, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f <code>string_view<\/code>.  <\/p>\n<pre><code class=\"cpp\">namespace Impl {     template &lt;typename MaybeString>      inline constexpr bool isString = std::is_convertible_v&lt;MaybeString, std::string>;      template &lt;>        inline constexpr bool isString&lt;std::string_view> = true;  \/\/ 'cause is not implicitly convertible to std::string }<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u0438 \u0435\u0441\u043b\u0438 \u0441\u0438\u043b \u0440\u0430\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c, \u0442\u043e \u043d\u0435 \u0440\u0430\u0434\u0443\u0435\u043c\u0441\u044f. \u041d\u043e \u0435\u0441\u043b\u0438 \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c, \u0442\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d <code>auto makeString(const String&amp; s)<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u043f\u043e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043a\u043e\u043f\u0438\u044e. \u0414\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 <code>makeString(std::string(\"world\"));<\/code> \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u043f\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435. <\/p>\n<p><a class=\"anchor\" name=\"perfect_forwarding\" id=\"perfect_forwarding\"><\/a><\/p>\n<h4>\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 std::forward<\/h4>\n<p>\u0418\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u043e\u0441\u044c (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u043e\u0432 \u0442\u043e\u043c\u0443 \u043d\u0430\u0437\u0430\u0434), \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043d\u0430\u0448\u0435\u0433\u043e <code>makeString<\/code> \u0431\u044b\u043b\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u0430\u044f lvalue-\u0441\u0441\u044b\u043b\u043a\u0430. \u041d\u043e \u0440\u0430\u0437 \u0443 \u043d\u0430\u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u043e <a href=\"https:\/\/habr.com\/ru\/post\/242639\/\" rel=\"noopener noreferrer nofollow\">\u0438\u0434\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0438 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u0421++<\/a>: \u0435\u0441\u043b\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a <code>T&amp;&amp;<\/code>, \u0442\u043e \u043f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u043a lvalue-\u0441\u0441\u044b\u043b\u043a\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>std::string&amp;<\/code> \u0438\u043b\u0438 <code>const string&amp;<\/code>), \u0442\u0430\u043a \u0438 rvalue-\u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 <code>std::string&amp;&amp;<\/code>. <\/p>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 rvalue \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u0432\u0438\u0434\u043e\u0432 lvalue. \u041f\u043e\u0434\u043d\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432\u044b\u0448\u0435, \u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e <code>T&amp;&amp;<\/code> \u0432 \u043e\u0431\u044c\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0442\u0435\u043c \u0436\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>std::forward<\/code>, \u0438\u043b\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0432 rvalue \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>std::move<\/code>, \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a lvalue. <\/p>\n<p><a href=\"https:\/\/cppinsights.io\/lnk?code=c3RydWN0IEEgeyBpbnQgaSA9IDA7IH07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gdm9pZCBmdXJ0aGVyQ2FsbChUJiYgZnVydGhlclBhcmFtZXRlcikgCnsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+IHZvaWQgdXBwZXJDYWxsKFQmJiBwYXJhbWV0ZXIpIAp7CQogIC8vIGFsd2F5cyBmdXJ0aGVyQ2FsbDxUJj4gb3IgZnVydGhlckNhbGw8Y29uc3QgVCY+IGJlYWNzdWUgb2YgbGFjayBvZiBzdGQ6OmZvcndhcmQKICBmdXJ0aGVyQ2FsbChwYXJhbWV0ZXIpOyAgCn0KCkEgZ2V0QTMoKSB7IHJldHVybiBBezN9O30KCmludCBtYWluKCkKewogICAgQSBhMSB7IDEgfTsKICAgIGNvbnN0IEEgYTIgeyAyIH07CgogICAgdXBwZXJDYWxsKGExKTsgICAgICAgICAvLyB1cHBlckNhbGw8QSY+CiAgICB1cHBlckNhbGwoYTIpOyAgICAgICAgIC8vIHVwcGVyQ2FsbDxjb25zdCBBJj4KICAgIHVwcGVyQ2FsbChnZXRBMygpKTsgICAgLy8gdXBwZXJDYWxsPEEmJj4KfQo=&amp;insightsOptions=cpp2a&amp;std=cpp2a&amp;rev=1.0\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u0438 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439<\/a> \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u043d\u0430 CppInsight, \u043f\u043e\u043a\u0430 \u0436\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/forward\" rel=\"noopener noreferrer nofollow\">std::forward<\/a> \u043d\u0430\u043c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u0434\u0430\u043b\u044c\u0448\u0435 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>std::string<\/code>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0443\u0441\u043e\u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">template&lt;class T> void wrapper(T&amp;&amp; arg)  {     \/\/ arg is always lvalue     foo(std::forward&lt;T>(arg)); \/\/ Forward as lvalue or as rvalue, depending on T }<\/code><\/pre>\n<ul>\n<li>\n<p> If a call to <code>wrapper()<\/code> passes an rvalue <code>std::string<\/code>, then <code>T<\/code> is deduced to <code>std::string<\/code> (not <code>std::string&amp;<\/code>, <code>const std::string&amp;<\/code>, or <code>std::string&amp;&amp;<\/code>), and <code>std::forward<\/code> ensures that an rvalue reference is passed to <code>foo<\/code>. <\/p>\n<\/li>\n<li>\n<p> If a call to <code>wrapper()<\/code> passes a const lvalue <code>std::string<\/code>, then <code>T<\/code> is deduced to <code>const std::string&amp;<\/code>, and <code>std::forward<\/code> ensures that a const lvalue reference is passed to <code>foo<\/code>. <\/p>\n<\/li>\n<li>\n<p> If a call to <code>wrapper()<\/code> passes a non-const lvalue <code>std::string<\/code>, then <code>T<\/code> is deduced to <code>std::string&amp;<\/code>, and <code>std::forward<\/code> ensures that a non-const lvalue reference is passed to <code>foo<\/code>. <\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0442\u0435\u043d\u0438\u044f \u0442\u043e\u043d\u043d\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043c \u043a \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a:<\/p>\n<pre><code class=\"cpp\">template &lt;typename String> auto makeString(String&amp;&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(std::forward&lt;String>(s)); }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u043d\u043e \u0440\u0430\u0434\u0443\u0435\u043c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <em>Step Into<\/em> \u043e\u0442\u043b\u0430\u0434\u0447\u0438\u043a\u0430 \u0437\u0430\u0439\u0434\u0435\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>std::string(std::string&amp;&amp;)<\/code>  \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0437\u043e\u0432\u0430 <code>makeString(std::string(\"!!1\"))<\/code> \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u0423 \u043c\u0435\u043d\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e &#8212; \u044f \u0434\u043e\u0432\u043e\u043b\u0435\u043d.<\/p>\n<pre><code class=\"cpp\">\/\/ main.cpp #include &lt;iostream> #include &lt;vector> #include &lt;set>  #include \"makeString.hpp\"  struct A  {     std::string to_string() const { return \"A\"; } };  struct B {     int m_i = 0;     std::string to_string() const { return \"B{\" + std::to_string(m_i) + \"}\"; } };  int main() {     A a;     B b = {1};      const std::vector&lt;int> xs = {1, 2, 3};     const std::set&lt;float> ys = {4, 5, 6};     const double zs[] = {7, 8, 9};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14) &lt;&lt; std::endl               &lt;&lt; \"xs: \" &lt;&lt; makeString(xs) &lt;&lt; \"; ys: \" &lt;&lt; makeString(ys)                &lt;&lt; \"; zs: \" &lt;&lt; makeString(zs)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"Hello, \")                &lt;&lt; makeString(std::string_view(\"world\"))                &lt;&lt; makeString(std::string(\"!!1\"))                &lt;&lt; std::endl;      const std::string constHello = \"const hello!\";     std::cout &lt;&lt; makeString(constHello)               &lt;&lt; std::endl; }<\/code><\/pre>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits>  namespace Impl {     template &lt;typename MaybeString>      inline constexpr bool isString = std::is_convertible_v&lt;MaybeString, std::string>;      template &lt;>        inline constexpr bool isString&lt;std::string_view> = true;  \/\/ 'cause is not implicitly convertible to std::string }  template &lt;typename Object> auto makeString(const Object &amp;object) -> decltype(object.to_string()) {     return object.to_string(); }  template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }  template &lt;typename Iterable> auto makeString(const Iterable &amp;iterable)      -> std::enable_if_t&lt;!Impl::isString&lt;Iterable>,                           decltype(makeString(*std::begin(iterable)))> {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;typename String> auto makeString(String&amp;&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(std::forward&lt;String>(s)); }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"variadic_pt1\" id=\"variadic_pt1\"><\/a><\/p>\n<h4>Variadic templates &#8212; \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432  <\/h4>\n<p>\u041c\u0435\u043d\u0435\u0435 \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u0440 \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0441\u043f\u0440\u043e\u0441\u0438\u043b \u0431\u044b \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f, \u043d\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043b\u0438 \u0435\u043c\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043d\u0430 48 \u0441\u0442\u0440\u043e\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430 &#8212; \u043e\u0442\u0441\u0442\u0443\u043f\u044b, \u0438 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 <code>main()<\/code> \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0432 20 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430, \u043d\u0430 \u0434\u043e\u0431\u0440\u043e\u0442\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e &#171;\u043d\u0435 \u0442\u044f\u043d\u0443\u0442&#187;. <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043a\u0430\u043a \u043d\u0430\u0441\u0447\u0435\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>makeString(\"xs: \", xs, \"; and float is: \", 3.14f);<\/code>? \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u044b \u0433\u0440\u043e\u0437\u044f\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0431\u0435\u0441\u0441\u043e\u043d\u043d\u043e\u0439 \u043d\u043e\u0447\u044c\u044e \u0441 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c, \u0430 \u0436\u0438\u0437\u043d\u044c &#8212; \u043a\u043e\u0440\u043e\u0442\u043a\u0430, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0441\u0441\u043e\u043d\u043d\u044b\u0445 \u043d\u043e\u0447\u0435\u0439 \u0441 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0432 \u043d\u0435\u0439 \u043c\u0430\u043b\u043e, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u0435 \u0432 \u044d\u0442\u043e\u043c \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0438. <\/p>\n<p>\u0420\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u0437\u0430\u0434\u0430\u0447\u0443 \u0435\u0449\u0435 \u0440\u0430\u0437:<\/p>\n<pre><code class=\"cpp\">std::cout &lt;&lt; makeString(\"xs: \", xs, \"; and float is: \", 3.14f)            &lt;&lt; std::endl;<\/code><\/pre>\n<p>\u0418 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0435\u043c \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0443\u0442\u0435\u0439 \u0440\u0435\u0448\u0435\u043d\u0438\u044f: <code>makeString<\/code> \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 &#8212; \u044d\u0442\u043e \u043a\u0430\u043a <code>makeString<\/code> \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c, \u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, <code>makeString(a, b, c)<\/code> \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e <code>makeString(a) + makeString(b) + makeString(c);<\/code> <\/p>\n<p><a class=\"anchor\" name=\"variadic_recursion\" id=\"variadic_recursion\"><\/a><\/p>\n<h4>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a variadic templates<\/h4>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0438\u0437 \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0445 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u0438\u0434\u0435\u0439 \u0437\u0432\u0443\u0447\u0438\u0442 \u0442\u0430\u043a: <code>makeString(first, rest...)<\/code> => <code>makeString(first) + makeString(rest...);<\/code> \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 <code>rest<\/code> \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439. \u0410 \u043a\u043e\u0433\u0434\u0430 <code>rest<\/code> \u043f\u0443\u0441\u0442\u043e\u0439, \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043e\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">std::string makeString() {     return std::string(); }  template &lt;typename First, typename... Rest> std::string makeString(First &amp;&amp;first, Rest &amp;&amp;...rest) {     return makeString(std::forward&lt;First>(first))           + makeString(std::forward&lt;Rest>(rest)...); }<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0440\u0430\u043b\u0438, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438, \u0443\u043f\u0430\u043b\u0438. \u041a \u0441\u0447\u0430\u0441\u0442\u044c, \u043d\u0435 \u043f\u043e\u0434 \u0441\u0442\u043e\u043b, \u0430 \u043f\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e <code>segmentation fault<\/code>. \u0421\u0443\u0440\u043e\u0432\u044b\u0435 \u043b\u0438\u043d\u0443\u043a\u0441\u043e\u0438\u0434\u044b \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f CppInsight, \u0430 \u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 VS 2019 \u0441\u043c\u043e\u0442\u0440\u044f\u0442 \u043d\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0438 \u0443\u0436\u0435 \u0432\u0438\u0434\u044f\u0442, \u0447\u0442\u043e:<\/p>\n<blockquote>\n<p>warning C4717: &#8216;makeString&lt;A &amp;>&#8217;: recursive on all control paths, function will cause runtime stack oveflow<\/p>\n<\/blockquote>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0432\u044b\u0437\u043e\u0432 <code>makeString(std::forward(first))<\/code> \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u0437\u043e\u0432\u0443 <code>std::string makeString(First&amp;&amp; first, Rest&amp;&amp; ...rest)<\/code> \u0441 \u043f\u0443\u0441\u0442\u044b\u043c parameter-pack <code>Rest<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0441\u043d\u043e\u0432\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c <code>makeString(First&amp;&amp; first, Rest&amp;&amp; ...rest)<\/code>\u0441 \u043f\u0443\u0441\u0442\u044b\u043c Rest. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438 \u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043a\u0430. <\/p>\n<p>\u041d\u043e \u0435\u0441\u043b\u0438 <code>makeString<\/code> \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0434\u0432\u0443\u0445 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438 \u043e\u0441\u0442\u0430\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b, \u0442\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430 <code>makeString<\/code> \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0446\u0435\u043b\u0430\u044f \u043f\u0430\u0447\u043a\u0430. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">template &lt;typename First, typename Second, typename... Rest> std::string makeString(First&amp;&amp; first, Second&amp;&amp; second, Rest&amp;&amp;... rest) { return makeString(std::forward&lt;First>(first))         + makeString(std::forward&lt;Second>(second), std::forward&lt;Rest>(rest)...); }<\/code><\/pre>\n<p>\u041e\u043a\u0438\u043d\u0435\u043c \u0432\u0437\u0433\u043b\u044f\u0434\u043e\u043c \u0432\u0435\u0441\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u043f\u0435\u0440\u0435\u0434 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0435\u0439 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits>  namespace Impl {     template &lt;typename MaybeString>      inline constexpr bool isString = std::is_convertible_v&lt;MaybeString, std::string>;      template &lt;>        inline constexpr bool isString&lt;std::string_view> = true;  \/\/ 'cause is not implicitly convertible to std::string }  template &lt;typename Object> auto makeString(const Object &amp;object) -> decltype(object.to_string()) {     return object.to_string(); }  template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }  template &lt;typename Iterable> auto makeString(const Iterable &amp;iterable)      -> std::enable_if_t&lt;!Impl::isString&lt;Iterable>,                          decltype(makeString(*std::begin(iterable)))> {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;typename String> auto makeString(String&amp;&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(std::forward&lt;String>(s)); }  template &lt;typename First, typename Second, typename... Rest> std::string makeString(First&amp;&amp; first, Second&amp;&amp; second, Rest&amp;&amp;... rest) {   return makeString(std::forward&lt;First>(first))           + makeString(std::forward&lt;Second>(second), std::forward&lt;Rest>(rest)...); }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u0440\u0430\u0434\u0443\u0435\u043c\u0441\u044f \u0432\u044b\u0432\u043e\u0434\u0443:<\/p>\n<pre><code>a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 Hello, world!!1 const hello! xs: 1;2;3; and float is: 3.140000<\/code><\/pre>\n<p><a class=\"anchor\" name=\"variadic_fold\" id=\"variadic_fold\"><\/a><\/p>\n<h4>\u041f\u043e\u0434\u0445\u043e\u0434 \u0441\u043e \u0441\u0432\u0435\u0440\u0442\u043a\u043e\u0439 (fold expression) \u043a Variadic templates<\/h4>\n<p>\u0423\u0436\u0435 \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043b\u0443\u0447\u0448\u0435: \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0442\u0430\u043c, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0432\u0435\u0440\u043d\u0443\u0442\u044c &#171;\u043f\u0430\u0447\u043a\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432&#187; c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e\u0436\u0435 \u0436\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u041a \u0441\u0447\u0430\u0442\u044c\u044e, \u043c\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0447\u0438\u0442\u0430\u043b\u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/fold\" rel=\"noopener noreferrer nofollow\">\u0432 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u0441\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0435<\/a>, \u0447\u0442\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 17\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 \u0432 C++ \u0435\u0441\u0442\u044c <em>fold expression<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0430\u0447\u043a\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u0432 \u043e\u0434\u043d\u0443 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438. <\/p>\n<p>\u0418\u043c\u0435\u044f \u0443\u043d\u0430\u0440\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e <code>result += x[n]<\/code>, \u0433\u0434\u0435 <code>x[n]<\/code> &#8212; \u044d\u0442\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 <code>makeString(pack[n])<\/code> , \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u044f \u043f\u0440\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u0434\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0438 \u0433\u043e\u0440\u044c\u043a\u0438\u0439 \u043e\u043f\u044b\u0442 \u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u043a\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0441\u0432\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f <em>parameter pack<\/em> \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0435 1, \u0442.\u043a. <em>parameter pack<\/em> \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1 \u0443\u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c. <\/p>\n<pre><code class=\"cpp\">template &lt;typename... Pack> auto makeString(Pack&amp;&amp;... pack)  -> std::enable_if_t&lt;(sizeof...(Pack) > 1), std::string> {     return (... += makeString(std::forward&lt;Pack>(pack))); }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043e\u043a\u0438\u043d\u0435\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u0437\u0433\u044f\u043b\u043e\u043c \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">\/\/ main.cpp  #include &lt;iostream> #include &lt;vector> #include &lt;set>  #include \"makeString.hpp\"  struct A  {     std::string to_string() const { return \"A\"; } };  struct B {     int m_i = 0;     std::string to_string() const { return \"B{\" + std::to_string(m_i) + \"}\"; } };  int main() {     A a;     B b = {1};      const std::vector&lt;int> xs = {1, 2, 3};     const std::set&lt;float> ys = {4, 5, 6};     const double zs[] = {7, 8, 9};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14) &lt;&lt; std::endl               &lt;&lt; \"xs: \" &lt;&lt; makeString(xs) &lt;&lt; \"; ys: \" &lt;&lt; makeString(ys)                &lt;&lt; \"; zs: \" &lt;&lt; makeString(zs)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"Hello, \")                &lt;&lt; makeString(std::string_view(\"world\"))                &lt;&lt; makeString(std::string(\"!!1\"))                &lt;&lt; std::endl;      const std::string constHello = \"const hello!\";     std::cout &lt;&lt; makeString(constHello)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"xs: \", xs, \"; and float is: \", 3.14f)                &lt;&lt; std::endl; }<\/code><\/pre>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits>  namespace Impl {     template &lt;typename MaybeString>      inline constexpr bool isString = std::is_convertible_v&lt;MaybeString, std::string>;      template &lt;>        inline constexpr bool isString&lt;std::string_view> = true;  \/\/ 'cause is not implicitly convertible to std::string }  template &lt;typename Object> auto makeString(const Object &amp;object) -> decltype(object.to_string()) {     return object.to_string(); }  template &lt;typename Numeric> auto makeString(Numeric value) -> decltype(std::to_string(value)) {     return std::to_string(value); }  template &lt;typename Iterable> auto makeString(const Iterable &amp;iterable)      -> std::enable_if_t&lt;!Impl::isString&lt;Iterable>,                          decltype(makeString(*std::begin(iterable)))> {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;typename String> auto makeString(String&amp;&amp; s)     -> std::enable_if_t&lt;Impl::isString&lt;String>, std::string> {     return std::string(std::forward&lt;String>(s)); }  template &lt;typename... Pack> auto makeString(Pack&amp;&amp;... pack) -> std::enable_if_t&lt;(sizeof...(Pack) > 1), std::string> {     return (... += makeString(std::forward&lt;Pack>(pack))); }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code>a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 Hello, world!!1 const hello! xs: 1;2;3; and float is: 3.140000<\/code><\/pre>\n<p>\u042d\u0442\u0438\u043c \u043a\u043e\u0434\u043e\u043c \u044f \u0434\u043e\u0432\u043e\u043b\u0435\u043d \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f. \u041d\u043e \u0435\u0441\u043b\u0438 \u0431\u044b \u044f-\u0438\u0437-\u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u0448\u0435\u043b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043a \u0441\u0435\u0431\u0435-\u0441\u0435\u0439\u0447\u0430\u0441, \u044f \u0431\u044b \u0441\u0435\u0431\u0435 \u0441\u043a\u0430\u0437\u0430\u043b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u0434 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u043e\u0432, \u0442.\u043a. \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430\u043c\u0438 \u043f\u0440\u043e\u0448\u0438\u0432\u043e\u043a \u0434\u043b\u044f \u0445\u043e\u043b\u043e\u0434\u0438\u043b\u044c\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"concepts\" id=\"concepts\"><\/a><\/p>\n<h4>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f (constraints) &#8212; \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0430\u0445\u0430\u0440 \u0434\u043b\u044f SFINAE<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u044f \u043e\u0431\u043d\u043e\u0432\u0438\u043b Visual Studio 2019 \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 16.3, \u0438\u043b\u0438 g\u0441\u0441 \u0438 libstdcpp \u0434\u043e 10-\u0439, \u044f \u0431\u044b \u0441\u043c\u043e\u0433 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u0434\u043b\u044f SFINAE. <\/p>\n<p>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u044b &#8212; \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0442\u0438\u043f\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u041f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 std::enable_if \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. <\/p>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430\u043c\u0438, <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/constraints\" rel=\"noopener noreferrer nofollow\">\u043a\u0430\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u044f\u0437\u044b\u043a\u0430 \u0421++<\/a> \u043f\u043e\u0431\u043b\u0438\u0436\u0435:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T>  concept IsString = std::is_convertible_v&lt;T, std::string>                  || std::is_same_v&lt;T, std::string_view>;  template &lt;IsString String> std::string makeString(String&amp;&amp; s) {     return std::string(std::forward&lt;String>(s)); }<\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u0437\u0434\u0435\u0441\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u044f\u0437\u044b\u043a\u0430 \u0437\u0430\u0434\u0430\u043d \u043a\u043e\u043d\u0446\u0435\u043f\u0442 <code>IsString<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u0442\u0435 \u0442\u0438\u043f\u044b, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0431\u0443\u043b\u0435\u0432\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 <code>is_convertible_v&lt;T, std::string><br \/> || is_same_v&lt;T, std::string_view><\/code>, \u0433\u0434\u0435 <code>is_convertible_v<\/code> \u0438 <code>is_same_v<\/code> &#8212; \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>type_traits<\/code>. \u0414\u0430\u043b\u0435\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>makeString<\/code>, \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043b\u044e\u0431\u043e\u0439 <code>typename<\/code>, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0442 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044e <code>IsString<\/code>. <\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u0438\u043f\u044b. \u041f\u0443\u0441\u0442\u044c \u043a\u043e\u043d\u0446\u0435\u043f\u0442 <code>HasStdConversion&lt;T><\/code> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0447\u0442\u043e \u043a\u043e\u0434 <code>T a; std::to_string(a);<\/code> \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> concept HasStdConversion = requires (T number) { std::to_string(number); };<\/code><\/pre>\n<p>\u041f\u043e-\u043c\u043e\u0435\u043c\u0443, \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435. \u041d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0439\u0442\u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0438 \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043a \u0442\u0438\u043f\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430, <s>\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u044f\u0442 \u043c\u0435\u043d\u044f \u043b\u0438\u043d\u0433\u0432\u0438\u0441\u0442\u044b \u0437\u0430 4 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0434\u0440\u044f\u0434<\/s>. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0442\u0438\u043f\u0443 \u0431\u0435\u0437\u043e \u0432\u0441\u044f\u043a\u0438\u0445 <code>decltype()<\/code> \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u0438\u0437 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/concepts\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u043e\u0432<\/a>. <\/p>\n<p>\u041f\u0443\u0441\u0442\u044c <code>HasToString<\/code> \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u0430 <code>object.to_string()<\/code> \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u043b \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0443 <code>std::is_convertible&lt;T, std::string><\/code>:<\/p>\n<pre><code class=\"cpp\">#include &lt;comcepts> \/\/ standard library concepts template &lt;typename T>  concept HasToString = requires (const T&amp; object)  {      { object.to_string() } -> std::convertible_to&lt;std::string>;  };  template &lt;HasToString Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }<\/code><\/pre>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u044f\u0432\u043d\u043e. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u043e\u0432 \u0432 \u044f\u0434\u0440\u0435 \u0421++, \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c, \u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u044b\u043c, \u043a\u0430\u043a \u0432 \u043d\u0430\u0448\u0438\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f\u0445 <code>makeString<\/code>.<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u043b \u0441\u0440\u0430\u0437\u0443 \u0434\u0432\u0443\u043c \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u044b\u043b \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c, \u0438 \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u043e\u0439? \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440-\u0441\u0442\u0440\u043e\u043a\u0430 \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440-\u043d\u043e-\u043d\u0435-\u0441\u0442\u0440\u043e\u043a\u0430, \u043d\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0439 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u0438\u043a\u043e\u0439 \u043d\u0435\u0442 \u043d\u0443\u0436\u0434\u044b, \u0442.\u043a. \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430, \u043d\u043e \u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430. <\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b <code>IsContainer<\/code>, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0438 <code>IsString<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a\u0438. \u0422\u043e\u0433\u0434\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 makeString \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0434\u0432\u0430 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0435\u0451 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> concept IsContainer = requires (const T&amp; container) { std::begin(container); };  template &lt;typename T>  concept IsString = std::is_convertible_v&lt;T, std::string>                  || std::is_same_v&lt;T, std::string_view>;  template &lt;typename Container> requires (IsContainer&lt;Container> &amp;&amp; !IsString&lt;Container>) std::string makeString(const Container&amp; iterable) {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u0435 <code>makeString<\/code>, <code>typename Container<\/code> &#8212; \u044d\u0442\u043e \u0442\u0438\u043f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f IsConainer \u0438 <code>not IsString<\/code>. <\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0438 \u043f\u043e-\u043c\u043e\u0435\u043c\u0443, \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f  \u043d\u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c:<\/p>\n<pre><code class=\"cpp\">template &lt;typename... Pack> requires (sizeof...(Pack) > 1) std::string makeString(Pack&amp;&amp;... pack) {     return (... += makeString(std::forward&lt;Pack>(pack))); }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"why_better\" id=\"why_better\"><\/a><\/p>\n<h4>\u0421\u0442\u0430\u043b\u043e \u043b\u0438 \u0441 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430\u043c\u0438 \u043b\u0443\u0447\u0448\u0435?<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"cpp\">#include &lt;map> \/\/... int main() { \/\/ ...     std::map&lt;int, int> keys = { {1,2}, { 3,4} };     makeString(keys); }<\/code><\/pre>\n<p>\u0418 \u043e\u0446\u0435\u043d\u0438\u043c \u0432\u044b\u0432\u043e\u0434 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code>[build] In file included from ..\/main.cpp:6: [build] ..\/makeString.hpp: In instantiation of \u2018std::string makeString(const Container&amp;) [with Container = std::map&lt;int, int>; std::string = std::__cxx11::basic_string&lt;char>]\u2019: [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:49:29: error: no matching function for call to \u2018makeString(const std::pair&lt;const int, int>&amp;)\u2019 [build]    49 |         result += makeString(i); [build]       |                   ~~~~~~~~~~^~~ [build] ..\/makeString.hpp:29:13: note: candidate: \u2018std::string makeString(const Object&amp;) [with Object = std::pair&lt;const int, int>; std::string = std::__cxx11::basic_string&lt;char>]\u2019 [build]    29 | std::string makeString(const Object&amp; object) [build]       |             ^~~~~~~~~~ [build] ..\/makeString.hpp:29:13: note: constraints not satisfied [build] ..\/makeString.hpp:35:13: note: candidate: \u2018std::string makeString(Numeric) [with Numeric = std::pair&lt;const int, int>; std::string = std::__cxx11::basic_string&lt;char>]\u2019 [build]    35 | std::string makeString(Numeric value) [build]       |             ^~~~~~~~~~ [build] ..\/makeString.hpp:35:13: note: constraints not satisfied [build] ..\/makeString.hpp:42:13: note: candidate: \u2018std::string makeString(const Container&amp;) [with Container = std::pair&lt;const int, int>; std::string = std::__cxx11::basic_string&lt;char>]\u2019 [build]    42 | std::string makeString(const Container&amp; iterable) [build]       |             ^~~~~~~~~~ [build] ..\/makeString.hpp:42:13: note: constraints not satisfied [build] ninja: build stopped: subcommand failed. [build] Build finished with exit code 1<\/code><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a, \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f makeString \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 26 \u043c\u043e\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u0440\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c makeString \u0434\u043b\u044f pair&lt;int, int>, \u0442.\u043a. \u043d\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u043d\u0435 \u043f\u043e\u0434\u043e\u0448\u0451\u043b \u043f\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>\u0414\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0437\u0430\u043c\u0435\u043d\u044e makeString.hpp \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e \u0431\u0435\u0437 Concepts<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>build] ..\/main.cpp: In function \u2018int main()\u2019: [build] ..\/main.cpp:26:20: error: no matching function for call to \u2018makeString(std::map&lt;int, int>&amp;)\u2019 [build]    26 |     makeString(keys); [build]       |                    ^ [build] In file included from ..\/main.cpp:6: [build] ..\/makeString.hpp:16:6: note: candidate: \u2018template&lt;class Object> decltype (object.to_string()) makeString(const Object&amp;)\u2019 [build]    16 | auto makeString(const Object &amp;object) -> decltype(object.to_string()) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:16:6: note:   template argument deduction\/substitution failed: [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Object> decltype (object.to_string()) makeString(const Object&amp;) [with Object = std::map&lt;int, int>]\u2019: [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:16:58: error: \u2018const class std::map&lt;int, int>\u2019 has no member named \u2018to_string\u2019 [build]    16 | auto makeString(const Object &amp;object) -> decltype(object.to_string()) [build]       |                                                   ~~~~~~~^~~~~~~~~ [build] ..\/makeString.hpp:22:6: note: candidate: \u2018template&lt;class Numeric> decltype (std::__cxx11::to_string(value)) makeString(Numeric)\u2019 [build]    22 | auto makeString(Numeric value) -> decltype(std::to_string(value)) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:22:6: note:   template argument deduction\/substitution failed: [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Numeric> decltype (std::__cxx11::to_string(value)) makeString(Numeric) [with Numeric = std::map&lt;int, int>]\u2019: [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:22:58: error: no matching function for call to \u2018to_string(std::map&lt;int, int>&amp;)\u2019 [build]    22 | auto makeString(Numeric value) -> decltype(std::to_string(value)) [build]       |                                            ~~~~~~~~~~~~~~^~~~~~~ [build] In file included from \/usr\/include\/c++\/10\/string:55, [build]                  from \/usr\/include\/c++\/10\/bits\/locale_classes.h:40, [build]                  from \/usr\/include\/c++\/10\/bits\/ios_base.h:41, [build]                  from \/usr\/include\/c++\/10\/ios:42, [build]                  from \/usr\/include\/c++\/10\/ostream:38, [build]                  from \/usr\/include\/c++\/10\/iostream:39, [build]                  from ..\/main.cpp:1: [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6597:3: note: candidate: \u2018std::string std::__cxx11::to_string(int)\u2019 [build]  6597 |   to_string(int __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6597:17: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018int\u2019 [build]  6597 |   to_string(int __val) [build]       |             ~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6608:3: note: candidate: \u2018std::string std::__cxx11::to_string(unsigned int)\u2019 [build]  6608 |   to_string(unsigned __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6608:22: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018unsigned int\u2019 [build]  6608 |   to_string(unsigned __val) [build]       |             ~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6616:3: note: candidate: \u2018std::string std::__cxx11::to_string(long int)\u2019 [build]  6616 |   to_string(long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6616:18: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018long int\u2019 [build]  6616 |   to_string(long __val) [build]       |             ~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6627:3: note: candidate: \u2018std::string std::__cxx11::to_string(long unsigned int)\u2019 [build]  6627 |   to_string(unsigned long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6627:27: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018long unsigned int\u2019 [build]  6627 |   to_string(unsigned long __val) [build]       |             ~~~~~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6635:3: note: candidate: \u2018std::string std::__cxx11::to_string(long long int)\u2019 [build]  6635 |   to_string(long long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6635:23: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018long long int\u2019 [build]  6635 |   to_string(long long __val) [build]       |             ~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6647:3: note: candidate: \u2018std::string std::__cxx11::to_string(long long unsigned int)\u2019 [build]  6647 |   to_string(unsigned long long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6647:32: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018long long unsigned int\u2019 [build]  6647 |   to_string(unsigned long long __val) [build]       |             ~~~~~~~~~~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6658:3: note: candidate: \u2018std::string std::__cxx11::to_string(float)\u2019 [build]  6658 |   to_string(float __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6658:19: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018float\u2019 [build]  6658 |   to_string(float __val) [build]       |             ~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6667:3: note: candidate: \u2018std::string std::__cxx11::to_string(double)\u2019 [build]  6667 |   to_string(double __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6667:20: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018double\u2019 [build]  6667 |   to_string(double __val) [build]       |             ~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6676:3: note: candidate: \u2018std::string std::__cxx11::to_string(long double)\u2019 [build]  6676 |   to_string(long double __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6676:25: note:   no known conversion for argument 1 from \u2018std::map&lt;int, int>\u2019 to \u2018long double\u2019 [build]  6676 |   to_string(long double __val) [build]       |             ~~~~~~~~~~~~^~~~~ [build] In file included from ..\/main.cpp:6: [build] ..\/makeString.hpp:28:6: note: candidate: \u2018template&lt;class Iterable> std::enable_if_t&lt;(! isString&lt;Iterable>), decltype (makeString((* std::begin(iterable))))> makeString(const Iterable&amp;)\u2019 [build]    28 | auto makeString(const Iterable &amp;iterable) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:28:6: note:   template argument deduction\/substitution failed: [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Iterable> std::enable_if_t&lt;(! isString&lt;Iterable>), decltype (makeString((* std::begin(iterable))))> makeString(const Iterable&amp;) [with Iterable = std::map&lt;int, int>]\u2019: [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:30:44: error: no matching function for call to \u2018makeString(const std::pair&lt;const int, int>&amp;)\u2019 [build]    30 |                         decltype(makeString(*std::begin(iterable)))> [build]       |                                  ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ [build] ..\/makeString.hpp:16:6: note: candidate: \u2018template&lt;class Object> decltype (object.to_string()) makeString(const Object&amp;)\u2019 [build]    16 | auto makeString(const Object &amp;object) -> decltype(object.to_string()) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:16:6: note:   template argument deduction\/substitution failed: [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Object> decltype (object.to_string()) makeString(const Object&amp;) [with Object = std::pair&lt;const int, int>]\u2019: [build] ..\/makeString.hpp:30:44:   required by substitution of \u2018template&lt;class Iterable> std::enable_if_t&lt;(! isString&lt;Iterable>), decltype (makeString((* std::begin(iterable))))> makeString(const Iterable&amp;) [with Iterable = std::map&lt;int, int>]\u2019 [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:16:58: error: \u2018const struct std::pair&lt;const int, int>\u2019 has no member named \u2018to_string\u2019 [build]    16 | auto makeString(const Object &amp;object) -> decltype(object.to_string()) [build]       |                                                   ~~~~~~~^~~~~~~~~ [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Iterable> std::enable_if_t&lt;(! isString&lt;Iterable>), decltype (makeString((* std::begin(iterable))))> makeString(const Iterable&amp;) [with Iterable = std::map&lt;int, int>]\u2019: [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:22:6: note: candidate: \u2018template&lt;class Numeric> decltype (std::__cxx11::to_string(value)) makeString(Numeric)\u2019 [build]    22 | auto makeString(Numeric value) -> decltype(std::to_string(value)) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:22:6: note:   template argument deduction\/substitution failed: [build] ..\/makeString.hpp: In substitution of \u2018template&lt;class Numeric> decltype (std::__cxx11::to_string(value)) makeString(Numeric) [with Numeric = std::pair&lt;const int, int>]\u2019: [build] ..\/makeString.hpp:30:44:   required by substitution of \u2018template&lt;class Iterable> std::enable_if_t&lt;(! isString&lt;Iterable>), decltype (makeString((* std::begin(iterable))))> makeString(const Iterable&amp;) [with Iterable = std::map&lt;int, int>]\u2019 [build] ..\/main.cpp:26:20:   required from here [build] ..\/makeString.hpp:22:58: error: no matching function for call to \u2018to_string(std::pair&lt;const int, int>&amp;)\u2019 [build]    22 | auto makeString(Numeric value) -> decltype(std::to_string(value)) [build]       |                                            ~~~~~~~~~~~~~~^~~~~~~ [build] In file included from \/usr\/include\/c++\/10\/string:55, [build]                  from \/usr\/include\/c++\/10\/bits\/locale_classes.h:40, [build]                  from \/usr\/include\/c++\/10\/bits\/ios_base.h:41, [build]                  from \/usr\/include\/c++\/10\/ios:42, [build]                  from \/usr\/include\/c++\/10\/ostream:38, [build]                  from \/usr\/include\/c++\/10\/iostream:39, [build]                  from ..\/main.cpp:1: [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6597:3: note: candidate: \u2018std::string std::__cxx11::to_string(int)\u2019 [build]  6597 |   to_string(int __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6597:17: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018int\u2019 [build]  6597 |   to_string(int __val) [build]       |             ~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6608:3: note: candidate: \u2018std::string std::__cxx11::to_string(unsigned int)\u2019 [build]  6608 |   to_string(unsigned __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6608:22: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018unsigned int\u2019 [build]  6608 |   to_string(unsigned __val) [build]       |             ~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6616:3: note: candidate: \u2018std::string std::__cxx11::to_string(long int)\u2019 [build]  6616 |   to_string(long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6616:18: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018long int\u2019 [build]  6616 |   to_string(long __val) [build]       |             ~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6627:3: note: candidate: \u2018std::string std::__cxx11::to_string(long unsigned int)\u2019 [build]  6627 |   to_string(unsigned long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6627:27: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018long unsigned int\u2019 [build]  6627 |   to_string(unsigned long __val) [build]       |             ~~~~~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6635:3: note: candidate: \u2018std::string std::__cxx11::to_string(long long int)\u2019 [build]  6635 |   to_string(long long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6635:23: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018long long int\u2019 [build]  6635 |   to_string(long long __val) [build]       |             ~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6647:3: note: candidate: \u2018std::string std::__cxx11::to_string(long long unsigned int)\u2019 [build]  6647 |   to_string(unsigned long long __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6647:32: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018long long unsigned int\u2019 [build]  6647 |   to_string(unsigned long long __val) [build]       |             ~~~~~~~~~~~~~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6658:3: note: candidate: \u2018std::string std::__cxx11::to_string(float)\u2019 [build]  6658 |   to_string(float __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6658:19: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018float\u2019 [build]  6658 |   to_string(float __val) [build]       |             ~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6667:3: note: candidate: \u2018std::string std::__cxx11::to_string(double)\u2019 [build]  6667 |   to_string(double __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6667:20: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018double\u2019 [build]  6667 |   to_string(double __val) [build]       |             ~~~~~~~^~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6676:3: note: candidate: \u2018std::string std::__cxx11::to_string(long double)\u2019 [build]  6676 |   to_string(long double __val) [build]       |   ^~~~~~~~~ [build] \/usr\/include\/c++\/10\/bits\/basic_string.h:6676:25: note:   no known conversion for argument 1 from \u2018std::pair&lt;const int, int>\u2019 to \u2018long double\u2019 [build]  6676 |   to_string(long double __val) [build]       |             ~~~~~~~~~~~~^~~~~ [build] In file included from ..\/main.cpp:6: [build] ..\/makeString.hpp:44:6: note: candidate: \u2018template&lt;class String> std::enable_if_t&lt;isString&lt;String>, std::__cxx11::basic_string&lt;char> > makeString(String&amp;&amp;)\u2019 [build]    44 | auto makeString(String&amp;&amp; s) [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:44:6: note:   template argument deduction\/substitution failed: [build] In file included from \/usr\/include\/c++\/10\/bits\/move.h:57, [build]                  from \/usr\/include\/c++\/10\/bits\/nested_exception.h:40, [build]                  from \/usr\/include\/c++\/10\/exception:148, [build]                  from \/usr\/include\/c++\/10\/ios:39, [build]                  from \/usr\/include\/c++\/10\/ostream:38, [build]                  from \/usr\/include\/c++\/10\/iostream:39, [build]                  from ..\/main.cpp:1: [build] \/usr\/include\/c++\/10\/type_traits: In substitution of \u2018template&lt;bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = false; _Tp = std::__cxx11::basic_string&lt;char>]\u2019: [build] ..\/makeString.hpp:44:6:   required by substitution of \u2018template&lt;class String> std::enable_if_t&lt;isString&lt;String>, std::__cxx11::basic_string&lt;char> > makeString(String&amp;&amp;) [with String = std::map&lt;int, int>&amp;]\u2019 [build] ..\/main.cpp:26:20:   required from here [build] \/usr\/include\/c++\/10\/type_traits:2554:11: error: no type named \u2018type\u2019 in \u2018struct std::enable_if&lt;false, std::__cxx11::basic_string&lt;char> >\u2019 [build]  2554 |     using enable_if_t = typename enable_if&lt;_Cond, _Tp>::type; [build]       |           ^~~~~~~~~~~ [build] In file included from ..\/main.cpp:6: [build] ..\/makeString.hpp:51:6: note: candidate: \u2018template&lt;class ... Pack> std::enable_if_t&lt;(sizeof... (Pack) > 1), std::__cxx11::basic_string&lt;char> > makeString(Pack&amp;&amp; ...)\u2019 [build]    51 | auto makeString(Pack&amp;&amp;... pack) -> std::enable_if_t&lt;(sizeof...(Pack) > 1), std::string> [build]       |      ^~~~~~~~~~ [build] ..\/makeString.hpp:51:6: note:   template argument deduction\/substitution failed: [build] ninja: build stopped: subcommand failed. [build] Build finished with exit code 1<\/code><\/pre>\n<\/div>\n<\/details>\n<p><a class=\"anchor\" name=\"results\" id=\"results\"><\/a><\/p>\n<h4>\u0418\u0442\u043e\u0433\u0438<\/h4>\n<p>\u042f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u044f \u043f\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430\u043c \u0421++, \u0431\u044b\u043b\u0438 \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u044b \u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u044b \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043d\u0430\u0432\u044b\u043a\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u0435\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u043c \u0438 \u0441\u0441\u044b\u043b\u043e\u043a \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f, \u0430 \u0443 \u043c\u0435\u043d\u044f &#8212; \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d gcc. <\/p>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u0440\u0438\u0447\u0435\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u0435\u0449\u0435 \u0440\u0430\u0437, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043d\u0435\u0433\u043e, \u0438 \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<pre><code class=\"cpp\">\/\/ main.cpp #include &lt;iostream> #include &lt;vector> #include &lt;set>  #include \"makeString.hpp\"  struct A  {     std::string to_string() const { return \"A\"; } };  struct B {     int m_i = 0;     std::string to_string() const { return \"B{\" + std::to_string(m_i) + \"}\"; } };  int main() {     A a;     B b = {1};      const std::vector&lt;int> xs = {1, 2, 3};     const std::set&lt;float> ys = {4, 5, 6};     const double zs[] = {7, 8, 9};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14) &lt;&lt; std::endl               &lt;&lt; \"xs: \" &lt;&lt; makeString(xs) &lt;&lt; \"; ys: \" &lt;&lt; makeString(ys)                &lt;&lt; \"; zs: \" &lt;&lt; makeString(zs)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"Hello, \")                &lt;&lt; makeString(std::string_view(\"world\"))                &lt;&lt; makeString(std::string(\"!!1\"))                &lt;&lt; std::endl;      const std::string constHello = \"const hello!\";     std::cout &lt;&lt; makeString(constHello)               &lt;&lt; std::endl;      std::cout &lt;&lt; makeString(\"xs: \", xs, \"; and float is: \", 3.14f)                &lt;&lt; std::endl; }<\/code><\/pre>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;type_traits> #include &lt;concepts>  namespace Impl {  template &lt;typename T>  concept IsString = std::is_convertible_v&lt;T, std::string>                  || std::is_same_v&lt;T, std::string_view>;  template &lt;typename T>  concept HasToString = requires (const T&amp; object)  {      { object.to_string() } -> std::convertible_to&lt;std::string>;  };  template &lt;typename T> concept HasStdConversion = requires (T number) { std::to_string(number); };  template &lt;typename T> concept IsContainer = requires (const T&amp; container) { std::begin(container); };  }  template &lt;Impl::HasToString Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }  template &lt;Impl::HasStdConversion Numeric> std::string makeString(Numeric value) {     return std::to_string(value); }  template &lt;typename Container> requires (Impl::IsContainer&lt;Container> &amp;&amp; !Impl::IsString&lt;Container>) std::string makeString(const Container&amp; iterable) {     std::string result;     for (const auto &amp;i : iterable)     {         if (!result.empty())             result += ';';         result += makeString(i);     }      return result; }  template &lt;Impl::IsString String> std::string makeString(String&amp;&amp; s) {     return std::string(std::forward&lt;String>(s)); }  template &lt;typename... Pack> requires (sizeof...(Pack) > 1) std::string makeString(Pack&amp;&amp;... pack) {     return (... += makeString(std::forward&lt;Pack>(pack))); }<\/code><\/pre>\n<pre><code>a: A; b: B{1}; pi: 3.140000 xs: 1;2;3; ys: 4.000000;5.000000;6.000000; zs: 7.000000;8.000000;9.000000 Hello, world!!1 const hello! xs: 1;2;3; and float is: 3.140000<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/645321\/\"> https:\/\/habr.com\/ru\/post\/645321\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e <a href=\"https:\/\/habr.com\/ru\/post\/599801\/\" rel=\"noopener noreferrer nofollow\">\u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u0421++ \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445<\/a> \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0436\u0433\u0443\u0447\u0435\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435  \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u0445\u043e\u0436\u0435\u0435, \u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0434\u0430 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u0431\u044b\u043b \u043d\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u043c, \u0438 \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0443\u0447\u043d\u043e \u043d\u0435 \u0431\u044b\u043b\u043e. \u0410 \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u0447\u0435\u0433\u043e \u0431\u044b \u0442\u043e \u043d\u0438 \u0431\u044b\u043b\u043e \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0442\u043e \u044d\u0442\u0438\u043c \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u044b.  <\/p>\n<h3>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#problem\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#start\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#simple\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#overloading\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sfinae_pt1\" rel=\"noopener noreferrer nofollow\">SFINAE (Substitution Failure Is Not An Error) &#8212; \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u0442\u043e \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0433\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sfinae_pt2\" rel=\"noopener noreferrer nofollow\">SFINAE \u0438 trailing return type<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#collections\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c makeString() \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#strings\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c makeString() \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#traits\" rel=\"noopener noreferrer nofollow\">Type traits &#8212; \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0438\u043f\u043e\u0432 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043f\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u043c\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 (by Non-type template parameter)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#cppinsight\" rel=\"noopener noreferrer nofollow\">\u0427\u0442\u043e \u0436\u0435 \u0442\u044b, ____ [\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440], \u0434\u0435\u043b\u0430\u0435\u0448\u044c&#8230; <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#std_type_traits\" rel=\"noopener noreferrer nofollow\">\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 type_traits <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#perfect_forwarding\" rel=\"noopener noreferrer nofollow\">\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 std::forward<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_pt1\" rel=\"noopener noreferrer nofollow\">Variadic templates &#8212; \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_recursion\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a variadic templates<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#variadic_fold\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0445\u043e\u0434 \u0441\u043e \u0441\u0432\u0435\u0440\u0442\u043a\u043e\u0439 (fold expression) \u043a Variadic templates<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#concepts\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f (constraints) &#8212; \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0430\u0445\u0430\u0440 \u0434\u043b\u044f SFINAE<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"http:\/\/why_better\" rel=\"noopener noreferrer nofollow\">\u0421\u0442\u0430\u043b\u043e \u043b\u0438 \u0441 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430\u043c\u0438 \u043b\u0443\u0447\u0448\u0435?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#results\" rel=\"noopener noreferrer nofollow\">\u0418\u0442\u043e\u0433\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"problem\" id=\"problem\"><\/a><\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h3>\n<p>\u0412 \u0438\u043c\u0435\u044e\u0449\u0435\u043c\u0441\u044f <code>std::to_string<\/code> \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u043a\u043e\u0432: <\/p>\n<ul>\n<li>\n<p>\u043e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0435 \u043d\u0430\u043c\u0438. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0435\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u043f\u044b\u0442 \u0438 \u043c\u043e\u0440\u0435 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u043a\u0435\u043c-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u043c.<\/p>\n<\/li>\n<li>\n<p>\u043e\u043d \u043d\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e <code>std<\/code> \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0438 \u0434\u0430\u0436\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/extending_std\" rel=\"noopener noreferrer nofollow\">\u043e \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/a>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0436\u0430\u0440\u043a\u0438\u0435 \u0441\u043f\u043e\u0440\u044b \u0432 \u043a\u0443\u0440\u0438\u043b\u043a\u0435. <\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <code>makeString<\/code> \u0441 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043e\u0442 <code>std::to_string<\/code> \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430\u043c\u0438. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043a \u043d\u0435\u043c\u0443 \u0431\u0443\u0434\u0443\u0442:<\/p>\n<ul>\n<li>\n<p>\u0441\u0445\u043e\u0436\u0438\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441: <code>makeString(3.14);<\/code> \u0438 <code>makeString(directionVector);<\/code> \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437 \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u044c. \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u044c\u043b\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430  <code>class UserRequest;<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>std::string to_string() const;<\/code> \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u043d\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434 <code>to_string<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u0434 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0421++ \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c &#171;\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187; \u0432 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 Ubuntu 20.04.3 LTS \u0438\u043b\u0438 VS 2019 Community Edition. \u0410 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0431\u044b\u043b \u0447\u0438\u0441\u0442\u044b\u0439 C++, \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0431\u044b\u0442\u044c \u0441 \u043d\u0430\u043c\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0436\u0435. \u042f \u043f\u0435\u0440\u0435\u0434\u0430\u043c \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0441\u044c\u0431\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CMake-\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0438 \u0431\u0443\u0434\u0443 \u043d\u0430\u0434\u0435\u044f\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0443 \u0421++ \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432 \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u044d\u0442\u0438 \u0440\u0443\u043d\u044b \u0432 \u0441\u0432\u043e\u044e \u043b\u044e\u0431\u0438\u043c\u0443\u044e IDE \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u043b\u044e\u0431\u0438\u043c\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430. <\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cmake\">cmake_minimum_required(VERSION 3.0.0) project(makeString VERSION 0.1.0)  add_executable(makeString main.cpp)  set(CMAKE_CXX_EXTENSIONS OFF)      # no vendor-specific extensions set_property(TARGET makeString PROPERTY CXX_STANDARD 20)  if (MSVC)     target_compile_options(makeString PUBLIC \/W4 \/WX \/Za \/permissive-) else()     target_compile_options(makeString PUBLIC -Wall -Wextra -pedantic -Werror) endif()<\/code><\/pre>\n<h3>\u041e\u043f\u044b\u0442 \u0438 \u043c\u043e\u0440\u0435 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f<\/h3>\n<p><a class=\"anchor\" name=\"start\" id=\"start\"><\/a><\/p>\n<p>\u0418 \u0442\u0430\u043a, \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 \u0421++:<\/p>\n<pre><code class=\"cpp\">#include &lt;iostream> #include \"makeString.hpp\"  struct A {     std::string to_string() const { return \"A\"; } };  struct B {     int m_i = 0;     std::string to_string() const { return \"B{\" + std::to_string(m_i) + \"}\"; } };  int main() {     A a;     B b = {1};      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b); }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"simple\" id=\"simple\"><\/a><\/p>\n<h4>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/h4>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b <code>to_string<\/code> \u0443 \u043d\u0430\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043a\u0441\u043a\u0438 &#171;\u043f\u043e\u0434\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u043b\u0441\u044f&#187; \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0448\u0430\u0431\u043b\u043e\u043d. \u0428\u0430\u0431\u043b\u043e\u043d &#8212; \u044d\u0442\u043e \u0432\u0435\u0449\u044c, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435\u0445\u0438\u0442\u0440\u0430\u044f, \u043d\u043e \u0435\u0441\u043b\u0438 \u0443\u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/599801\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0433\u0434\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043e\u0441\u043d\u043e\u0432\u044b. <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0440\u0430\u043b\u0438, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442: <code>a: A; b: B{1}<\/code><\/p>\n<p><a class=\"anchor\" name=\"overloading\" id=\"overloading\"><\/a><\/p>\n<h4>\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h4>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>makeString(3.14)<\/code> \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0443 \u0442\u0438\u043f\u0430 <code>double<\/code> \u043d\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 <code>to_string<\/code>. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>std::to_string<\/code> \u0443 \u043d\u0430\u0441 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u0431\u0438\u0440\u0430\u043b, \u0438 \u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u043f\u0440\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. <\/p>\n<pre><code class=\"cpp\">int main() {   \/\/ ...      std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b)                &lt;&lt; \"; pi: \" &lt;&lt; makeString(3.14)               &lt;&lt; std::endl; }<\/code><\/pre>\n<pre><code class=\"cpp\">\/\/ makeString.hpp ... \/\/ [build] ..\/makeString.hpp:13:24: error:  \/\/ template-id \u2018makeString&lt;>\u2019 for \u2018std::string makeString(double)\u2019  \/\/ does not match any template declaration template &lt;> std::string makeString(double d) { return std::to_string(d); }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u0438\u043d &#8212; \u043a\u043e\u043c\u043e\u043c. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043e\u0439. \u041e\u0441\u0432\u0435\u0436\u0438\u0432 \u0441\u0432\u043e\u0438 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/template_specialization\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u043d\u0430 cppreference<\/a>, \u043c\u044b \u0435\u043c\u0443 \u043f\u043e\u043c\u043e\u0436\u0435\u043c, \u0438 \u043f\u043e\u043d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e <a href=\"https:\/\/godbolt.org\/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGEgJykrgAyeAyYAHI%2BAEaYxBIapAAOqAqETgwe3r4ByanpAqHhUSyx8VyJdpgOGUIETMQEWT5%2BXIFVNQJ1DQRFkTFxCbb1jc05bcM9fSVlCQCUtqhexMjsHASYLEkGGwDUJgDMbgQAnkmMrJi7ACqH2CYaAIKYqhvEDLsAbqh46LvosgA8klHCw8AAvTCArwECDXOaHKxPB6PDZbHZXQ7HM4XNg3O77J7fX67fioCBoBgKAj4swANl2qGi2mqBDm%2BwA7BZ\/kCQXgwZDobCmSyHAiDlYOQARFEotHbJh7LEElHEv5kikCam7MIEcwMvDskxcnmCYGgiFQmEQQ2I40y5FPanELwOXYADU5Fl1Ort0rtjsePpYTDCNsEuwawGQpF2yAQDQAVJHiMBPiYAKxWDNShHIrko3ZFj3F1Rerj2gOPYs6iN4fYHKW7MxVwvFjWqcVI6vt1Dk20S2XSjgLWicDO8PwcLSkVCcNzWay7BRLFaYswHHikAiaEcLADWIEkHIAdJJJAAODRcDNcMxmC8cg4HaRjjiSSe72ecXgKECJHdpxHUg4FgGBEBQVAtjoOJyEoNBoPoeJgAUZgkgUBBUAIPg6DeP8IGiL9ojCBoTk4LcELYM0GFoMigNILAQyMcR6PwYhWTwT5MD\/eiXmqGE1hnXVMDfGdaDwaJiFIjwsC\/AhiH5cjgKoAwUIANTwTAAHdgUYJSZEEEQxHYKQDPkJQ1C\/XQuH0QxjEXSx9Akv9IAWVA%2BS1TgAFpATMX8RI45wIFcMZWiCBh0GmAZyjyNJHAEUK9BSOKMii0pBhsjp4oYbpRk8Fo9Cy2oRl6MJ%2BnSmLqR6RLMpKtLZi4BYV2WVY9HkzA1h4Udx0\/ei5w4VQLzpLy6UkXZo2QXYIHkrwGH3dkIAXSxrFjXBCBIfYNxs3YPEQuJNs3OZeEArQFggJAEKSGCyAoTU9viZADCMAB9Ga5pw2g8MoQj6OI5hiDoiioKoghARouiZ0YuyWMhvB2JqLieJnPjkAEr9hNE3hxMk6SMEE46FJYJSFhUph1M0nTzinLd%2BEM0RxFM2nzJUdR6N0MxbKMFAHJsbGXIgNyPKpbzfP8%2BxspcCKavCyKypmDLYoKTJ8vGRXsvqhWiq6Erpa1nK6rl6LCp1lWwqqxoNfKJrV1amz2s64C3wnUgpxnfrBuG0a4ye4Apre%2BapqWqxHN2NaiGIA7tt2q6kIOswju3Xc5gPEAM0SN8P1IImOS4E8uA5HP88LguuHzl2v3639\/0ToCzvA86QCWAgkhhOC7pjhXMHwcO9CZoyGekJnFBZuT2Id0gtKkpJif0Hry76zghRbmlUCoXYPZGsaJr9l05oW6PrsjhOTr3UgEEwJgsHiAXZ\/fXgiYfE8L3vC9n4fN\/X\/pee3Z\/Wxq5P5OpBDwZjMCeDMt5\/AXkvCXekdI6S3wOL1H%2BHBjpJ26hwPy39eCVxrqdBYXFiBpGcJIIAA%3D%3D\" rel=\"noopener noreferrer nofollow\">\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 &#171;\u043f\u043e\u0434\u0447\u0438\u0441\u0442\u0438\u0442&#187;<\/a> \u0437\u0430 \u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435. \u0422\u0430\u043a \u0436\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u043a\u0440\u043e\u043c\u0435 <code>double<\/code> \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>float<\/code> \u0438  \u0435\u0449\u0435 7 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 <code>std::to_string<\/code>:<\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object &amp;object) {     return object.to_string(); }  template &lt;> std::string makeString(const double&amp; d) { return std::to_string(d); } template &lt;> std::string makeString(const float&amp; f)  { return std::to_string(f); } template &lt;> std::string makeString(const int&amp; i)    { return std::to_string(i); } \/\/ ... 6 more specializations ...<\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c, \u043e\u0434\u043d\u0430\u043a\u043e, \u0438 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043d\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. \u041a\u0440\u0430\u0435\u043c \u0433\u043b\u0430\u0437\u0430 \u0433\u043b\u044f\u043d\u0443\u0432 \u0440\u0430\u0437\u0434\u0435\u043b <em>Function template overloading<\/em> \u0432 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/function_template\" rel=\"noopener noreferrer nofollow\">\u0441\u0430\u0439\u0442\u0435<\/a>, \u0438\u043c\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0442.\u043a. \u043e\u043d\u0438 \u043d\u0435 \u043f\u043b\u0430\u0442\u044f\u0442 \u043c\u043d\u0435 \u0437\u0430 SEO. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u0430, \u043c\u043e\u0436\u043d\u043e \u043f\u043b\u043e\u0434\u043e\u0442\u0432\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0437\u0430 \u0435\u0451 \u0447\u0442\u0435\u043d\u0438\u0435\u043c \u043d\u0435 \u043e\u0434\u043d\u0438 \u0441\u0443\u0442\u043a\u0438. <\/p>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0433\u0434\u0430, \u0431\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434. \u041f\u043e\u0434\u0445\u043e\u0434 \u0441 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439, \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439, \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0435\u0435 \u043f\u0430\u0447\u043a\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. <\/p>\n<pre><code class=\"cpp\">\/\/ overloading instead of specializations std::string makeString(double d) { return std::to_string(d); } std::string makeString(float f)  { return std::to_string(f); } std::string makeString(int i)    { return std::to_string(i); } \/\/ ... 6 more overloads ...<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0437\u0430\u043f\u0443\u043a\u0441\u043a\u0430\u0435\u043c, \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e: <code>a: A; b: B{1}; pi: 3.140000<\/code><\/p>\n<p>\u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u044b \u0438\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u043c\u044b\u0441\u043b\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0443 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0451 \u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0448\u0430\u0431\u043b\u043e\u043d. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string>  template &lt;typename Object> std::string makeString(const Object&amp; object) {     return object.to_string(); }  \/*   [build] ..\/main.cpp: In function \u2018int main()\u2019:   [build] ..\/main.cpp:20:39: error: call of overloaded \u2018makeString(A&amp;)\u2019 is ambiguous   [build]    20 |     std::cout &lt;&lt; \"a: \" &lt;&lt; makeString(a) &lt;&lt; \"; b: \" &lt;&lt; makeString(b) *\/ template &lt;typename Numeric> std::string makeString(Numeric value) {     return std::to_string(value); } <\/code><\/pre>\n<p>\u0418 \u0432\u0435\u0434\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e: \u0435\u0441\u0442\u044c \u0432\u044b\u0437\u043e\u0432 <code>makeString(a)<\/code>, \u0433\u0434\u0435 <code>a<\/code> \u0432 \u043c\u0435\u0441\u0442\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f  <code>A&amp;<\/code> (<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/value_category\" rel=\"noopener noreferrer nofollow\">lvalue reference to A<\/a>), \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u043c\u0443 \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u043d\u0430\u0434\u043e \u044d\u0442\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u0442.\u043a. \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0435\u0440\u043d\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 \u043e\u0431\u0430 <em>\u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f (declaration)<\/em> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0432 <em>\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 (definition)<\/em> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u043d \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043b\u0435\u0437\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435 &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c&#187; \u043e\u0434\u043d\u0443 \u0438\u0437 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440 \u0438\u0437 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043e\u043a. \u0416\u0435\u043b\u0430\u043d\u0438\u0435 \u0435\u0441\u0442\u044c, \u0432 \u043d\u043e\u0440\u043c\u044b \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u043e\u0440\u0430\u043b\u0438 \u043e\u043d\u043e \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0435\u043c\u0443 \u043f\u0440\u043e\u0442\u0438\u0432\u0438\u0442\u044c\u0441\u044f, \u0432\u0435\u0434\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c&#8230;<\/p>\n<p><a class=\"anchor\" name=\"sfinae_pt1\" id=\"sfinae_pt1\"><\/a><\/p>\n<h4>SFINAE (Substitution Failure Is Not An Error) &#8212; \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u0442\u043e \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0433\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/h4>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0443 \u043d\u0438\u0445 (\u0443 \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u043f\u043b\u0430\u0442\u0438\u0442 \u043c\u043d\u0435 \u0437\u0430 SEO), <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/sfinae\" rel=\"noopener noreferrer nofollow\">SFINAE \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c<\/a>. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043d\u0435 \u0447\u0438\u0442\u0430\u0442\u044c, \u0430 \u043f\u0438\u0441\u0430\u0442\u044c: \u0435\u0441\u043b\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <strong><em>\u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445<\/em><\/strong> \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 <strong><em>\u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435<\/em><\/strong> \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f, \u0442\u043e \u044d\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0431\u0435\u0437 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e \u0438 \u0434\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. <\/p>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c&#187; \u043e\u0434\u0438\u043d \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0438\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438, \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f &#171;\u0432\u044b\u043a\u043b\u044e\u0447\u0430\u043c\u043e\u0439&#187; \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043c\u0435\u0441\u0442\u0435 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0430. \u041f\u0440\u043e\u044f\u0432\u0438\u0432 \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u044e, \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c \u0438 \u0441\u043c\u0435\u043a\u0430\u043b\u043a\u0443, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0439\u0442\u0438 \u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442: <\/p>\n<pre><code class=\"cpp\">\/\/ makeString.hpp #pragma once #include &lt;string> #include &lt;utility>  \/\/ for std::declval  \/\/ (1) template &lt;typename Object,            typename = decltype(std::declval&lt;Object>().to_string())> std::string makeString(const Object&amp; object) {     return object.to_string(); }  namespace Impl { bool acceptNumber(int); }  \/\/ (2) template &lt;typename Numeric> std::string makeString(Numeric value,                         decltype(Impl::acceptNumber(value))* = nullptr) {     return std::to_string(value); }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0440\u0443\u043d\u044b: <\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430: \u0442\u0438\u043f \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0438 \u0431\u0435\u0437\u044b\u043c\u044f\u043d\u044b\u0439 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u043e\u0433\u043e \u0436\u0435 \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <code>Object::to_string()<\/code> \u0434\u043b\u044f \u0441\u0444\u0435\u0440\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>Object<\/code> \u0432 \u0432\u0430\u043a\u0443\u0443\u043c\u0435. <code>std::declval&lt;Object><\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0430 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0442.\u043a. \u0443 \u0442\u0438\u043f\u0430 Object \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0431\u044b\u0442\u044c. <\/p>\n<p>\u0414\u043b\u044f \u0442\u0438\u043f\u043e\u0432 <code>A<\/code> \u0438 <code>B<\/code> \u0434\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>makeString<\/code>, \u043d\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0442\u0438\u043f\u0430 <code>double<\/code>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0442\u0438\u043f <code>std::declval&lt;double>().to_string()<\/code> \u0438 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u043e\u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435. <\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445 &#8212; \u044d\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <code>Impl::acceptNumber(value)<\/code>, \u0430 \u0442\u0430\u043a, \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 <code>acceptNumber<\/code> \u043e\u0431\u044c\u044f\u0432\u043b\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f int \u0438 \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043d\u0435\u044f\u0432\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c\u044b\u0445 \u043a \u043d\u0435\u043c\u0443, \u0442\u043e \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u043e\u0434\u0441\u0442\u0432\u0430\u0438\u0442\u044c \u0442\u0443\u0434\u0430 <code>struct A<\/code> \u0438\u043b\u0438 <code>struct B<\/code> \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0442\u0441\u044f \u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e. <code>dou<\/code><\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\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-327934","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/327934","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=327934"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/327934\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=327934"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=327934"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=327934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}