рдЖрдзреБрдирд┐рдХ рд╕реА ++ рдореЗрдВ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рддрд╛рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛


рдпрджрд┐ рдЖрдк C ++ рдореЗрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╢рд╛рдпрдж рд╕реЛрдЪреЗрдВ рдХрд┐ рдЖрдк рджреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЙрдирдХрд╛ рд╕рдВрдпреЛрдЬрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


auto str = "hello" + "world"; //   if ("hello" < "world") { // ,    ,   // ... } 

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ, "рдпрд╣ рдЕрд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред" рд╣рдо рдХрдЯ рдХреЗ рдиреАрдЪреЗ рд░реВрдврд╝рд┐рдпреЛрдВ рдХреЛ рддреЛрдбрд╝реЗрдВрдЧреЗ, рдФрд░ рд╕рдВрдХрд▓рди рдХреЗ рд╕реНрддрд░ рдкрд░ рд╕рд╣реА рд╣реЛрдВрдЧреЗред


рдпрд╣ рд╕рдм рдХреНрдпреЛрдВ рдЬрд░реВрд░реА рд╣реИ


рдЬрд┐рди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдореИрдВ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рдерд╛, рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛рдВрд╕реНрдЯреЗрдВрдЯ рдХреЗ рд░реВрдк рдореЗрдВ std :: string рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдкреНрд░рдерд╛ рдереАред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХрдИ рдореЙрдбреНрдпреВрд▓ рдереЗ рдЬрд┐рдирдореЗрдВ рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рд░рд╛рдВрдХ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдП рдЧрдП рдереЗ:


 // plugin.h const std::string PLUGIN_PATH = "/usr/local/lib/project/plugins/"; // ... 

 // sample_plugin.h const std::string SAMPLE_PLUGIN_LIB = PLUGIN_PATH + "sample.so"; // ... 

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд▓рд┐рдпрд╛ рдерд╛ рдХрд┐ рдПрдХ рджрд┐рди рдХреНрдпрд╛ рд╣реБрдЖред SAMPLE_PLUGIN_PATH рдиреЗ "sample.so" рдХрд╛ рдореВрд▓реНрдп рд▓рд┐рдпрд╛, рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ PLUGIN_PATH рдХрд╛ рдореВрд▓реНрдп "/usr/local/lib/project/plugins/" PLUGIN_PATH "/usr/local/lib/project/plugins/" , рдЕрдкреЗрдХреНрд╖рд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ред рдпрд╣ рдХреИрд╕реЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ? рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рд╡реИрд╢реНрд╡рд┐рдХ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдкреНрд░рд╛рд░рдВрдн рдХреЗ рдХреНрд░рдо рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдкреНрд░рд╛рд░рдВрдн рдХреЗ рд╕рдордп SAMPLE_PLUGIN_PATH рдЪрд░ PLUGIN_PATH рдЦрд╛рд▓реА рдерд╛ред


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдХрдИ рдиреБрдХрд╕рд╛рди рд╣реИрдВред рдкрд╣рд▓рд╛, рд╡реИрд╢реНрд╡рд┐рдХ рд╡рд╕реНрддреБ рдмрдирд╛рддреЗ рд╕рдордп рдлреЗрдВрдХрд╛ рдЧрдпрд╛ рдЕрдкрд╡рд╛рдж рдирд╣реАрдВ рдкрдХрдбрд╝рд╛ рдЧрдпрд╛ред рджреВрд╕рд░реЗ, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдореВрд▓реНрдпрд╡рд╛рди рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдордп рдЦрд░реНрдЪ рдХрд░рддрд╛ рд╣реИред


рдпрд╣ рддрдм рдерд╛ рдЬрдм рдореБрдЭреЗ рд╕рдВрдХрд▓рди рдордВрдЪ рдкрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдерд╛, рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рдЖрдЦрд┐рд░рдХрд╛рд░ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдирд╛ рдкрдбрд╝рд╛ред


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЙрди рдкрдВрдХреНрддрд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рд╕рдВрдХрд▓рди рдЪрд░рдг рдкрд░ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИрдВред рд╣рдо рдРрд╕реА рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рд╕реНрдерд┐рд░ рдХрд╣реЗрдВрдЧреЗред


рд╕реНрдЯреИрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЛрд░реНрд╕ рдХреЛрдб рдЬреАрдердм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ, рд▓рд┐рдВрдХ рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рд╣реИред


рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рд╕реЗ рдХрдо C ++ 14 рдЖрд╡рд╢реНрдпрдХ рд╣реИред


рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░рд┐рднрд╛рд╖рд╛;


рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╡рд░реНрдгреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣рдореЗрд╢рд╛ рдПрдХ рдЕрд╢рдХреНрдд рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддреА рд╣реИ:


 template<size_t Size> using static_string = std::array<const char, Size>; constexpr static_string<6> hello = {'H', 'e', 'l', 'l', 'o', '\0'}; 

рдпрд╣рд╛рдВ рдЖрдк рдПрдХ рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╡рд░реНрдгреЛрдВ рдХреЗ рдЯрдкрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╡рд┐рдХрд▓реНрдк рдореБрдЭреЗ рдЕрдзрд┐рдХ рд╕рдордп рд▓реЗрдиреЗ рд╡рд╛рд▓рд╛ рдФрд░ рдХрдо рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд▓рдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдпрд╣рд╛рдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рдирд╛


рдКрдкрд░ рджрд┐рдП рдЧрдП рд╣реИрд▓реЛ рд▓рд╛рдЗрди рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рджреЗрдЦреЗрдВ, рдпрд╣ рд╕рд┐рд░реНрдл рднрдпрд╛рдирдХ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рд╕рд░рдгреА рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдкреВрд░реНрд╡-рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рджреВрд╕рд░реЗ, рдЖрдкрдХреЛ рдЕрдВрдд рдореЗрдВ рдЕрд╢рдХреНрдд рдЪрд░рд┐рддреНрд░ рд▓рд┐рдЦрдирд╛ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред рддреАрд╕рд░рд╛, рдпреЗ рд╕рднреА рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо, рдХреЛрд╖реНрдардХ рдФрд░ рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрдиред рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдХреБрдЫ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИред рдореИрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛:


 constexpr auto hello = make_static_string("hello"); 

рдпрд╣рд╛рдБ рдЪрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдкреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣рдорд╛рд░реА рдорджрдж рдХрд░реЗрдЧрд╛, рдЬреЛ рд╣рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд╕реЗ рд╣рдорд╛рд░реЗ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреБрд▓ рдЖрд░рдВрдн рдХреЗ рд▓рд┐рдП рд╕рдВрдХреЗрдд рдХреЗ рд░реВрдк рдореЗрдВ рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХреЛрдВ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:


 template<size_t Size, size_t ... Indexes> constexpr static_string<sizeof ... (Indexes) + 1> make_static_string(const char (& str)[Size]) { return {str[Indexes] ..., '\0'}; } constexpr auto hello = make_static_string<0, 1, 2, 3, 4>("hello"); // hello == "hello" 

рдкрд╣рд▓реЗ рд╕реЗ рдмреЗрд╣рддрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдиреБрдХреНрд░рдорд┐рдд рдЕрднреА рднреА рд╣рд╛рде рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рд╣реИред рдпрд╣рд╛рдВ рд╣рдо рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рд╕рднреА рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдЖрдк рдЙрдиреНрд╣реЗрдВ рд░рд┐рд╡рд░реНрд╕ рдСрд░реНрдбрд░ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХрд╛ рдЙрд▓рдЯрд╛ рд╣реИ:


 constexpr hello1 = make_static_string<1, 2, 3>("hello"); // hello1 == "ell" constexpr hello2 = make_static_string<4, 3, 2, 1, 0>("hello"); // hello2 == "olleh" 

рдпрд╣ рд╡рд┐рдЪрд╛рд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред


рдЕрдм рд╣рдореЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдкрдВрдХреНрддрд┐ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХрд╛ рдХреНрд░рдо рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рдВрд╢рд╛рдиреБрдХреНрд░рдо рдЪрд╛рд▓ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдЦрд╛рд▓реА рд╕рдВрд░рдЪрдирд╛ (рдЖрдкрдХреЛ рдХреБрдЫ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:


 template<size_t ... Indexes> struct index_sequence {}; 

рд╣рдо рдПрдХ рдЬрдирд░реЗрдЯрд░ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рд╕рдВрдЪрдпрд┐рдд рдХрд░рддреЗ рд╣реБрдП рдПрдХ рдмрд╛рд░ рдореЗрдВ рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛:


 template<size_t Size, size_t ... Indexes> struct make_index_sequence : make_index_sequence<Size - 1, Size - 1, Indexes ...> {}; 

рд╣рдо рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рднреА рдзреНрдпрд╛рди рд░рдЦреЗрдВрдЧреЗ, рдЬрдм рд╕рднреА рд╕реВрдЪрдХрд╛рдВрдХ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВ (рдХрд╛рдЙрдВрдЯрд░ рд╢реВрдиреНрдп рд╣реИ), рд╣рдо рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдЬрдирд░реЗрдЯрд░ рдЙрд╕ рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдХреА рд╣рдореЗрдВ рдЬрд╝рд░реВрд░рдд рд╣реИ:


 template<size_t ... Indexes> struct make_index_sequence<0, Indexes ...> : index_sequence<Indexes ...> {}; 

рдирддреАрдЬрддрди, рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:


 template<size_t Size, size_t ... Indexes> constexpr static_string<sizeof ... (Indexes) + 1> make_static_string(const char (& str)[Size], index_sequence<Indexes ...>) { return {str[Indexes] ..., '\0'}; } 

рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рди рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ, рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛:


 template<size_t Size, size_t ... Indexes> constexpr static_string<sizeof ... (Indexes) + 1> make_static_string(const static_string<Size>& str, index_sequence<Indexes ...>) { return {str[Indexes] ..., '\0'}; } 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдЬреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ foo(const char (& str)[Size]) рд▓реЗрддрд╛ рд╣реИ, рд╣рдо рдПрдХ рд╕рдорд╛рди рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ foo(const static_string<Size>& str) рд▓реЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдЗрд╕рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ред


рдЪреВрдВрдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдХреА рд▓рдВрдмрд╛рдИ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЬрд╛рдиреА рдЬрд╛рддреА рд╣реИ, рд╣рдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдПрдХ рдХреНрд░рдо рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдКрдкрд░ рджрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдг рд▓рд┐рдЦреЗрдВрдЧреЗ:


 template<size_t Size> constexpr static_string<Size> make_static_string(const char (& str)[Size]) { return make_static_string(str, make_index_sequence<Size - 1>{}); } 

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╣рдореЗрдВ рдареАрдХ рд╡рд╣реА рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рд╣рдо рдЕрдзреНрдпрд╛рдп рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЪрд╛рд╣рддреЗ рдереЗред


рдпрджрд┐ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдПрдХ рдЦрд╛рд▓реА рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реМрдЯрд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЕрд╢рдХреНрдд рд╡рд░реНрдг рд╣реЛрддрд╛ рд╣реИ:


 constexpr static_string<1> make_static_string() { return {'\0'}; } 

рд╣рдореЗрдВ рд╡рд░реНрдгреЛрдВ рдХреЗ рдПрдХ рд╕рдореВрд╣ рд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 template<char ... Chars> constexpr static_string<sizeof ... (Chars) + 1> make_static_string(char_sequence<Chars ...>) { return {Chars ..., '\0'}; } 

рд╡реИрд╕реЗ, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╕рдм рдХреБрдЫ рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ рд╡рд░реНрдгрд┐рдд рддрдХрдиреАрдХреЛрдВ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЕрдЧрд░ рдХреБрдЫ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ, рддреЛ рдЕрдзреНрдпрд╛рдп рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрдврд╝рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред


рдПрдХ рдзрд╛рд░рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЖрдЙрдЯрдкреБрдЯ


рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░рд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдПрдХ рдЕрд╢рдХреНрдд рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдпрд╣ рд╕рд░рдгреА рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:


 template<size_t Size> std::ostream& operator<<(std::ostream& os, const static_string<Size>& str) { os << str.data(); return os; } 

рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ std :: string рдореЗрдВ рдмрджрд▓реЗрдВ


рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИред рд╣рдо рд╕рд░рдгреА рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ:


 template<size_t Size> std::string to_string(const static_string<Size>& str) { return std::string(str.data()); } 

рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рддреБрд▓рдирд╛


рд╣рдо рд╡рд░реНрдгреЛрдВ рдХреА рддреБрд▓рдирд╛ рд╡рд░реНрдг рд░реЗрдЦрд╛рдУрдВ рд╕реЗ рддрдм рддрдХ рдХрд░реЗрдВрдЧреЗ рдЬрдм рддрдХ рдХрд┐ рд╣рдо рдЕрдВрддрд░ рдирд╣реАрдВ рдЦреЛрдЬ рд▓реЗрддреЗ, рдпрд╛ рдЬрдм рддрдХ рд╣рдо рдХрдо рд╕реЗ рдХрдо рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЗ рдЕрдВрдд рддрдХ рдирд╣реАрдВ рдкрд╣реБрдБрдЪ рдЬрд╛рддреЗред рдЪреВрдВрдХрд┐ рдЕрднреА рддрдХ рдХрдмреНрдЬ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдирд╣реАрдВ рд╣реБрдЖ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдФрд░ рдЯрд░реНрдирд░реА рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:


 template<size_t Size1, size_t Size2> constexpr int static_string_compare( const static_string<Size1>& str1, const static_string<Size2>& str2, int index = 0) { return index >= Size1 && index >= Size2 ? 0 : index >= Size1 ? -1 : index >= Size2 ? 1 : str1[index] > str2[index] ? 1 : str1[index] < str2[index] ? -1 : static_string_compare(str1, str2, index + 1); } 

рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╣рдореЗрдВ рддреБрд▓рдирд┐рддреНрд░ рдХреЗ рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд╣рдо рдЙрдирдХреА рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕реВрдЪрдХрд╛рдВрдХ рдкреЗрд╢ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рд╣рдо рддреБрд▓рдирд╛ рдХрд┐рдП рдЧрдП рд╡рд░реНрдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рднреА рд╕реАрдорд┐рдд рдХрд░реЗрдВрдЧреЗ:


 template<size_t Size1, size_t Size2> constexpr int static_string_compare( const static_string<Size1>& str1, size_t index1, const static_string<Size2>& str2, size_t index2, size_t cur_length, size_t max_length) { return cur_length > max_length || (index1 >= Size1 && index2 >= Size2) ? 0 : index1 >= Size1 ? -1 : index2 >= Size2 ? 1 : str1[index1] > str2[index2] ? 1 : str1[index1] < str2[index2] ? -1 : static_string_compare(str1, index1 + 1, str2, index2 + 1, cur_length + 1, max_length); } 

рддреБрд▓рдирд┐рддреНрд░ рдХрд╛ рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг рд╣рдореЗрдВ рди рдХреЗрд╡рд▓ рдкреВрд░реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдмрд▓реНрдХрд┐ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рднреА рдХрд░реЗрдЧрд╛ред


рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХрд╛ рдХреЙрдирдЯреЗрдирдЯреЗрд╢рди


рд╕рдВрдШрдирди рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реНрдЯреИрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рдиреЗ рдкрд░ рдЕрдзреНрдпрд╛рдп рдХреЗ рд╕рдорд╛рди рд╡реИрд░рд┐рдПрдмрд▓ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдХреЗ рд╡рд░реНрдгреЛрдВ рдХреЗ рд╕рд╛рде рдкрд╣рд▓реЗ рд╕рд░рдгреА рдХреЛ рдирд┐рд░реВрдкрд┐рдд рдХрд░реЗрдВ (рдЕрд╢рдХреНрдд рд╡рд░реНрдг рдХреЛ рдЫреЛрдбрд╝рдХрд░), рдлрд┐рд░ рджреВрд╕рд░рд╛, рдФрд░ рдЕрдВрдд рдореЗрдВ рдЕрд╢рдХреНрдд рд╡рд░реНрдг рдХреЛ рдЕрдВрдд рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:


 template<size_t Size1, size_t ... Indexes1, size_t Size2, size_t ... Indexes2> constexpr static_string<Size1 + Size2 - 1> static_string_concat_2( const static_string<Size1>& str1, index_sequence<Indexes1 ...>, const static_string<Size2>& str2, index_sequence<Indexes2 ...>) { return {str1[Indexes1] ..., str2[Indexes2] ..., '\0'}; } template<size_t Size1, size_t Size2> constexpr static_string<Size1 + Size2 - 1> static_string_concat_2( const static_string<Size1>& str1, const static_string<Size2>& str2) { return static_string_concat_2(str1, make_index_sequence<Size1 - 1>{}, str2, make_index_sequence<Size2 - 1>{}); } 

рд╣рдо рд╕реНрдЯреНрд░рд┐рдВрдЧ рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреА рдПрдХ рдордирдорд╛рдиреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдорд╛рдкреНтАНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрд░рд┐рдПрдмрд▓ рдЯреЗрдореНтАНрдкрд▓реЗрдЯ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


 constexpr auto static_string_concat() { return make_static_string(); } template<typename Arg, typename ... Args> constexpr auto static_string_concat(Arg&& arg, Args&& ... args) { return static_string_concat_2(make_static_string(std::forward<Arg>(arg)), static_string_concat(std::forward<Args>(args) ...)); } 

рд╕реНрдЯреЗрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рд░реНрдЪ рдСрдкрд░реЗрд╢рди


рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреА рдЦреЛрдЬ рдФрд░ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред


рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреЗ рд▓рд┐рдП рдЦреЛрдЬреЗрдВ


рдЪрд░рд┐рддреНрд░ рдЦреЛрдЬ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХрдард┐рди рдирд╣реАрдВ рд╣реИ, рд╕рднреА рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдгреЛрдВ рдХреА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ рдФрд░ рдореИрдЪ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдкрд╣рд▓рд╛ рд╕реВрдЪрдХрд╛рдВрдХ рд▓реМрдЯрд╛рдПрдВред рд╣рдо рдЦреЛрдЬ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдФрд░ рдореИрдЪ рдХреА рдХреНрд░рдо рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рднреА рджреЗрдВрдЧреЗ:


 template<size_t Size> constexpr size_t static_string_find(const static_string<Size>& str, char ch, size_t from, size_t nth) { return Size < 2 || from >= Size - 1 ? static_string_npos : str[from] != ch ? static_string_find(str, ch, from + 1, nth) : nth > 0 ? static_string_find(str, ch, from + 1, nth - 1) : from; } 

рд╕реНрдерд┐рд░ static_string_npos рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЦреЛрдЬ рдЕрд╕рдлрд▓ рд░рд╣реАред рд╣рдо рдЗрд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


 constexpr size_t static_string_npos = std::numeric_limits<size_t>::max(); 

рдЗрд╕реА рддрд░рд╣, рд╣рдо рдПрдХ рдЦреЛрдЬ рдХреЛ рд╡рд┐рдкрд░реАрдд рджрд┐рд╢рд╛ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


 template<size_t Size> constexpr size_t static_string_rfind(const static_string<Size>& str, char ch, size_t from, size_t nth) { return Size < 2 || from > Size - 2 ? static_string_npos : str[from] != ch ? static_string_rfind(str, ch, from - 1, nth) : nth > 0 ? static_string_rfind(str, ch, from - 1, nth - 1) : from; } 

рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреА рдШрдЯрдирд╛ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг


рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреА рдШрдЯрдирд╛ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:


 template<size_t Size> constexpr bool static_string_contains(const static_string<Size>& str, char ch) { return static_string_find(str, ch) != static_string_npos; } 

рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ


рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рддреБрдЪреНрдЫ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рддреА рд╣реИ:


 template<size_t Size> constexpr size_t static_string_count(const static_string<Size>& str, char ch, size_t index) { return index >= Size - 1 ? 0 : (str[index] == ch ? 1 : 0) + static_string_count(str, ch, index + 1); } 

рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд▓рд┐рдП рдЦреЛрдЬреЗрдВ


рдЪреВрдВрдХрд┐ рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕реНрдереИрддрд┐рдХ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЫреЛрдЯреА рд╣реЛрдВрдЧреА, рд╣рдо рдпрд╣рд╛рдБ рдиреЙрдЯ-рдореЙрд░рд┐рд╕-рдкреНрд░реИрдЯ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд╣рдо рд╕рдмрд╕реЗ рд╕рд░рд▓ рджреНрд╡рд┐рдШрд╛рдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗ:


 template<size_t Size, size_t SubSize> constexpr size_t static_string_find(const static_string<Size>& str, const static_string<SubSize>& substr, size_t from, size_t nth) { return Size < SubSize || from > Size - SubSize ? static_string_npos : static_string_compare(str, from, substr, 0, 1, SubSize - 1) != 0 ? static_string_find(str, substr, from + 1, nth) : nth > 0 ? static_string_find(str, substr, from + 1, nth - 1) : from; } 

рдЗрд╕реА рддрд░рд╣, рд╣рдо рдПрдХ рдЦреЛрдЬ рдХреЛ рд╡рд┐рдкрд░реАрдд рджрд┐рд╢рд╛ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


 template<size_t Size, size_t SubSize> constexpr size_t static_string_rfind(const static_string<Size>& str, const static_string<SubSize>& substr, size_t from, size_t nth) { return Size < SubSize || from > Size - SubSize ? static_string_npos : static_string_compare(str, from, substr, 0, 1, SubSize - 1) != 0 ? static_string_rfind(str, substr, from - 1, nth) : nth > 0 ? static_string_rfind(str, substr, from - 1, nth - 1) : from; } 

рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреА рдШрдЯрдирд╛ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг


рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рдШрдЯрдирд╛ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:


 template<size_t Size, size_t SubSize> constexpr bool static_string_contains(const static_string<Size>& str, const static_string<SubSize>& substr) { return static_string_find(str, substr) != static_string_npos; } 

рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдХрд┐ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ рд╕реНрдЯреИрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ / рд╕рдорд╛рдкреНрдд рд╣реЛрддреА рд╣реИ


рдкрд╣рд▓реЗ рд╕реЗ рд╡рд░реНрдгрд┐рдд рддреБрд▓рдирд┐рддреНрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕реНрдереИрддрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рджрд┐рдП рдЧрдП рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ:


 template<size_t SubSize, size_t Size> constexpr bool static_string_starts_with(const static_string<Size>& str, const static_string<SubSize>& prefix) { return SubSize > Size ? false : static_string_compare(str, 0, prefix, 0, 1, SubSize - 1) == 0; } 

рдЗрд╕реА рддрд░рд╣ рдПрдХ рд╕реНрдерд┐рд░ рд▓рд╛рдЗрди рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:


 template<size_t SubSize, size_t Size> constexpr bool static_string_ends_with(const static_string<Size>& str, const static_string<SubSize>& suffix) { return SubSize > Size ? false : static_string_compare(str, Size - SubSize, suffix, 0, 1, SubSize - 1) == 0; } 

рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛


рдпрд╣рд╛рдВ рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рдЬреБрдбрд╝реЗ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВред


рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕реНрдерд╛рдирд╛рдкрдиреНрди, рдЙрдкрд╕рд░реНрдЧ рдФрд░ рдкреНрд░рддреНрдпрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛


рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ, рдПрдХ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рджрд┐рдП рдЧрдП рдкреНрд░рд╛рд░рдВрдн рдФрд░ рдЕрдВрдд рд╕реВрдЪрдХ рдХреЗ рд╕рд╛рде рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХрд╛ рдПрдХ рдХреНрд░рдо рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛:


 template<size_t Begin, size_t End, size_t ... Indexes> struct make_index_subsequence : make_index_subsequence<Begin, End - 1, End - 1, Indexes ...> {}; template<size_t Pos, size_t ... Indexes> struct make_index_subsequence<Pos, Pos, Indexes ...> : index_sequence<Indexes ...> {}; 

рд╣рдо static_assert рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рд╢реБрд░реБрдЖрдд рдФрд░ рдЕрдВрдд рдХреА рдЬрд╛рдБрдЪ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


 template<size_t Begin, size_t End, size_t Size> constexpr auto static_string_substring(const static_string<Size>& str) { static_assert(Begin <= End, "Begin is greater than End (Begin > End)"); static_assert(End <= Size - 1, "End is greater than string length (End > Size - 1)"); return make_static_string(str, make_index_subsequence<Begin, End>{}); } 

рдЙрдкрд╕рд░реНрдЧ рдПрдХ рдРрд╕рд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИ рдЬрд┐рд╕рдХреА рд╢реБрд░реБрдЖрдд рдореВрд▓ рд╕реНрдерд┐рд░ рд░реЗрдЦрд╛ рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд╕рд╛рде рд╣реЛрддреА рд╣реИ:


 template<size_t End, size_t Size> constexpr auto static_string_prefix(const static_string<Size>& str) { return static_string_substring<0, End>(str); } 

рдкреНрд░рддреНрдпрдп рдХреЗ рд▓рд┐рдП рдЗрд╕реА рддрд░рд╣, рдХреЗрд╡рд▓ рдЕрдВрдд рдореИрдЪ:


 template<size_t Begin, size_t Size> constexpr auto static_string_suffix(const static_string<Size>& str) { return static_string_substring<Begin, Size - 1>(str); } 

рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛


рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЙрдкрд╕рд░реНрдЧ рдФрд░ рдкреНрд░рддреНрдпрдп рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:


 template<size_t Index, size_t Size> constexpr auto static_string_split(const static_string<Size>& str) { return std::make_pair(static_string_prefix<Index>(str), static_string_suffix<Index + 1>(str)); } 

рд╕реНрдЯреИрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд░рд┐рд╡рд░реНрд╕рд▓


рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдЙрд▓рдЯрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдЬрдирд░реЗрдЯрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рд░рд┐рд╡рд░реНрд╕ рдСрд░реНрдбрд░ рдореЗрдВ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ:


 template<size_t Size, size_t ... Indexes> struct make_reverse_index_sequence : make_reverse_index_sequence<Size - 1, Indexes ..., Size - 1> {}; template<size_t ... Indexes> struct make_reverse_index_sequence<0, Indexes ...> : index_sequence<Indexes ...> {}; 

рдЕрдм рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдЯреИрдЯрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдЙрд▓рдЯ рджреЗрддрд╛ рд╣реИ:


 template<size_t Size> constexpr auto static_string_reverse(const static_string<Size>& str) { return make_static_string(str, make_reverse_index_sequence<Size - 1>{}); } 

рд╕реНрдереИрддрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИрд╢ рдЧрдгрдирд╛


рд╣рдо рдирд┐рдореНрди рд╕реВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣реИрд╢ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВрдЧреЗ:


H (s) = (s 0 + 1) + 33 0 + (s 1 + 1) 1 33 1 + ... + (s n - 1 + 1) n 33 n - 1 + 5381 n 33 n mod 2 64


 template<size_t Size> constexpr unsigned long long static_string_hash(const static_string<Size>& str, size_t index) { return index >= Size - 1 ? 5381ULL : static_string_hash(str, index + 1) * 33ULL + str[index] + 1; } 

рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд


рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкреВрд░реНрдгрд╛рдВрдХ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╡реНрдпреБрддреНрдХреНрд░рдо рдХреЛ рднреА рджреЗрдЦрддреЗ рд╣реИрдВред рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ long long рдкреНрд░рдХрд╛рд░ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ unsigned long long , рдпреЗ рдмрдбрд╝реА рдХреНрд╖рдорддрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ рд╣реЛрддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рдд, рд╡реЗ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реЛрддреЗ рд╣реИрдВред


рдХрд┐рд╕реА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓реЗрдВ


рдХрд┐рд╕реА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рднреА рдЕрдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╣реЛрдВрдЧреЗ, рдЙрдиреНрд╣реЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рд╡рд░реНрдгреЛрдВ рдореЗрдВ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрди рд╡рд░реНрдгреЛрдВ рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рдиреА рд╣реЛрдЧреАред


рдХрд┐рд╕реА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рднреА рдЕрдВрдХреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрдВрдбреЗрдХреНрд╕ рдЕрдиреБрдХреНрд░рдо рдЬрдирд░реЗрдЯрд░ рдХреЗ рд╕рдорд╛рди рдПрдХ рдЬрдирд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рд╡рд░реНрдгреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:


 template<char ... Chars> struct char_sequence {}; 

рд╣рдо рдПрдХ рдЕрдВрдХ рдЪрд░рд┐рддреНрд░ рдЬрдирд░реЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рд╕рдВрдЦреНрдпрд╛рдПрдБ, рдЕрдЧрд▓рд╛ рдЕрдВрдХ рдЕрдиреБрдХреНрд░рдо рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рджрд╕ рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 template<unsigned long long Value, char ... Chars> struct make_unsigned_int_char_sequence : make_unsigned_int_char_sequence<Value / 10, '0' + Value % 10, Chars ...> {}; 

рдпрджрд┐ рд╡рд░реНрддрдорд╛рди рд╕рдВрдЦреНрдпрд╛ 0 рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рдЕрдВрдХреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ, рдХрдиреНрд╡рд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ:


 template<char ... Chars> struct make_unsigned_int_char_sequence<0, Chars ...> : char_sequence<Chars ...> {}; 

рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рд╢реВрдиреНрдп рд╣реЛрдиреЗ рдкрд░ рдЖрдкрдХреЛ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ рднреА рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЖрдкрдХреЛ рдПрдХ рдЕрд╢рдХреНрдд рдЪрд░рд┐рддреНрд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рд╢реВрдиреНрдп рдХреЛ рд╡рд░реНрдгреЛрдВ рдХреЗ рдЦрд╛рд▓реА рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдлрд┐рд░ рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ:


 template<> struct make_unsigned_int_char_sequence<0> : char_sequence<'0'> {}; 

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдЬрдирд░реЗрдЯрд░ рд╕рдХрд╛рд░рд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдирдХрд╛рд░рд╛рддреНрдордХ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реИред рд╣рдо рд╢реБрд░реБрдЖрдд рдореЗрдВ рдПрдХ рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рдХрд░ рдПрдХ рдирдпрд╛ рдЬрдирд░реЗрдЯрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ - рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рд╕рдВрдХреЗрдд:


 template<bool Negative, long long Value, char ... Chars> struct make_signed_int_char_sequence {}; 

рд╣рдо рдКрдкрд░ рджрд┐рдЦрд╛рдП рдЧрдП рдЕрдиреБрд╕рд╛рд░ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╕рд╛рдЗрди рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП:


 template<long long Value, char ... Chars> struct make_signed_int_char_sequence<true, Value, Chars ...> : make_signed_int_char_sequence<true, Value / 10, '0' + -(Value % 10), Chars ...> {}; template<long long Value, char ... Chars> struct make_signed_int_char_sequence<false, Value, Chars ...> : make_signed_int_char_sequence<false, Value / 10, '0' + Value % 10, Chars ...> {}; 

рдпрд╣рд╛рдВ рдПрдХ рд╕реВрдХреНрд╖реНрдо рдмрд┐рдВрджреБ рд╣реИ, рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ -(Value % 10) ред рдпрд╣рд╛рдВ, рдЖрдк -Value % 10 рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐ рдирдХрд╛рд░рд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рд╕реАрдорд╛ рд╕рдХрд╛рд░рд╛рддреНрдордХрддрд╛ рдХреА рд╕реАрдорд╛ рд╕реЗ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдЕрдзрд┐рдХ рд╣реИ рдФрд░ рдиреНрдпреВрдирддрдо рд╕рдВрдЦреНрдпрд╛ рдорд╛рдкрд╛рдВрдХ рдорд╛рдиреНрдп рдорд╛рдиреЛрдВ рдХреЗ рд╕реЗрдЯ рд╕реЗ рдмрд╛рд╣рд░ рдЖрддрд╛ рд╣реИред


рд╣рдо рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд╛рдж рдирдВрдмрд░ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рдпрджрд┐ рдпрд╣ рдЛрдгрд╛рддреНрдордХ рд╣реИ, рддреЛ рдЛрдг рдЪрд┐рд╣реНрди рдЪрд┐рдиреНрд╣ рдЬреЛрдбрд╝реЗрдВ:


 template<char ... Chars> struct make_signed_int_char_sequence<true, 0, Chars ...> : char_sequence<'-', Chars ...> {}; template<char ... Chars> struct make_signed_int_char_sequence<false, 0, Chars ...> : char_sequence<Chars ...> {}; 

рдЕрд▓рдЧ рд╕реЗ, рд╣рдо рд╢реВрдиреНрдп рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрддреЗ рд╣реИрдВ:


 template<> struct make_signed_int_char_sequence<false, 0> : char_sequence<'0'> {}; 

рдЕрдВрдд рдореЗрдВ, рд╣рдо рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


 template<unsigned long long Value> constexpr auto uint_to_static_string() { return make_static_string(make_unsigned_int_char_sequence<Value>{}); } template<long long Value> constexpr auto int_to_static_string() { return make_static_string(make_signed_int_char_sequence<(Value < 0), Value>{}); } 

рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмрджрд▓реЗрдВ


рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡рд░реНрдгреЛрдВ рдХреЛ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝рдХрд░, рдкрд╣рд▓реЗ рд╡рд╛рд▓реА рд╢рдХреНрддрд┐ рд╕реЗ рджрд╕рд┐рдпреЛрдВ рдЧреБрдгрд╛ рдЧреБрдгрд╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╣рдо рд╕рднреА рдХреНрд░рд┐рдпрд╛рдПрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд░реВрдк рд╕реЗ рдХрд░рддреЗ рд╣реИрдВ, рдПрдХ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╣рдо рд╢реВрдиреНрдп рдкрд░ рд▓реМрдЯрддреЗ рд╣реИрдВ:


 template<size_t Size> constexpr unsigned long long static_string_to_uint(const static_string<Size>& str, size_t index) { return Size < 2 || index >= Size - 1 ? 0 : (str[index] - '0') + 10ULL * static_string_to_uint(str, index - 1); } template<size_t Size> constexpr unsigned long long static_string_to_uint(const static_string<Size>& str) { return static_string_to_uint(str, Size - 2); } 

рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЛрдгрд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдПрдБ рдЛрдг рдЪрд┐рд╣реНрди рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИрдВ:


 template<size_t Size> constexpr long long static_string_to_int(const static_string<Size>& str, size_t index, size_t first) { return index < first || index >= Size - 1 ? 0 : first == 0 ? (str[index] - '0') + 10LL * static_string_to_int(str, index - 1, first) : -(str[index] - '0') + 10LL * static_string_to_int(str, index - 1, first); } template<size_t Size> constexpr long long static_string_to_int(const static_string<Size>& str) { return Size < 2 ? 0 : str[0] == '-' ? static_string_to_int(str, Size - 2, 1) : static_string_to_int(str, Size - 2, 0); } 

рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рдпреЛрдЬреНрдпрддрд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░


рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдмрд┐рдВрджреБ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИрдВред рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗред


рд╕реНрдереИрддрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡рд╕реНрддреБ


рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдкреИрдХ рдХрд░реЗрдВред рдпрд╣ рдЫреЛрдЯреА рд╡рд┐рдзрд┐ рдХреЗ рдирд╛рдо рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рд╕рд╛рде рд╣реА рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛:


 template<size_t Size> struct static_string { constexpr size_t length() const { return Size - 1; } constexpr size_t size() const { return Size; } constexpr size_t begin() const { return 0; } constexpr size_t end() const { return Size - 1; } constexpr size_t rbegin() const { return Size - 2; } constexpr size_t rend() const { return std::numeric_limits<size_t>::max(); } constexpr bool empty() const { return Size < 2; } constexpr auto reverse() const { return static_string_reverse(*this); } template<size_t Begin, size_t End> constexpr auto substring() const { return static_string_substring<Begin, End>(*this); } template<size_t End> constexpr auto prefix() const { return static_string_prefix<End>(*this); } template<size_t Begin> constexpr auto suffix() const { return static_string_suffix<Begin>(*this); } constexpr size_t find(char ch, size_t from = 0, size_t nth = 0) const { return static_string_find(*this, ch, from, nth); } template<size_t SubSize> constexpr size_t find(const static_string<SubSize>& substr, size_t from = 0, size_t nth = 0) const { return static_string_find(*this, substr, from, nth); } template<size_t SubSize> constexpr size_t find(const char (& substr)[SubSize], size_t from = 0, size_t nth = 0) const { return static_string_find(*this, substr, from, nth); } constexpr size_t rfind(char ch, size_t from = Size - 2, size_t nth = 0) const { return static_string_rfind(*this, ch, from, nth); } template<size_t SubSize> constexpr size_t rfind(const static_string<SubSize>& substr, size_t from = Size - SubSize, size_t nth = 0) const { return static_string_rfind(*this, substr, from, nth); } template<size_t SubSize> constexpr size_t rfind(const char (& substr)[SubSize], size_t from = Size - SubSize, size_t nth = 0) const { return static_string_rfind(*this, substr, from, nth); } constexpr bool contains(char ch) const { return static_string_contains(*this, ch); } template<size_t SubSize> constexpr bool contains(const static_string<SubSize>& substr) const { return static_string_contains(*this, substr); } template<size_t SubSize> constexpr bool contains(const char (& substr)[SubSize]) const { return static_string_contains(*this, substr); } template<size_t SubSize> constexpr bool starts_with(const static_string<SubSize>& prefix) const { return static_string_starts_with(*this, prefix); } template<size_t SubSize> constexpr bool starts_with(const char (& prefix)[SubSize]) const { return static_string_starts_with(*this, prefix); } template<size_t SubSize> constexpr bool ends_with(const static_string<SubSize>& suffix) const { return static_string_ends_with(*this, suffix); } template<size_t SubSize> constexpr bool ends_with(const char (& suffix)[SubSize]) const { return static_string_ends_with(*this, suffix); } constexpr size_t count(char ch) const { return static_string_count(*this, ch); } template<size_t Index> constexpr auto split() const { return static_string_split<Index>(*this); } constexpr unsigned long long hash() const { return static_string_hash(*this); } constexpr char operator[](size_t index) const { return data[index]; } std::string str() const { return to_string(*this); } std::array<const char, Size> data; }; 


. :


 template<size_t Size1, size_t Size2> constexpr bool operator<(const static_string<Size1>& str1, const static_string<Size2>& str2) { return static_string_compare(str1, str2) < 0; } 

> <= >= == !=, . - .



:


 #define ITOSS(x) int_to_static_string<(x)>() #define UTOSS(x) uint_to_static_string<(x)>() #define SSTOI(x) static_string_to_int((x)) #define SSTOU(x) static_string_to_uint((x)) 


.


:


 constexpr auto hello = make_static_string("Hello"); constexpr auto world = make_static_string("World"); constexpr auto greeting = hello + ", " + world + "!"; // greeting == "Hello, World!" 

, :


 constexpr int apples = 5; constexpr int oranges = 7; constexpr auto message = static_string_concat("I have ", ITOSS(apples), " apples and ", ITOSS(oranges), ", so I have ", ITOSS(apples + oranges), " fruits"); // message = "I have 5 apples and 7 oranges, so I have 12 fruits" 

 constexpr unsigned long long width = 123456789ULL; constexpr unsigned long long height = 987654321ULL; constexpr auto message = static_string_concat("A rectangle with width ", UTOSS(width), " and height ", UTOSS(height), " has area ", UTOSS(width * height)); // message = "A rectangle with width 123456789 and height 987654321 has area 121932631112635269" 

 constexpr long long revenue = 1'000'000LL; constexpr long long costs = 1'200'000LL; constexpr long long profit = revenue - costs; constexpr auto message = static_string_concat("The first quarter has ended with net ", (profit >= 0 ? "profit" : "loss "), " of $", ITOSS(profit < 0 ? -profit : profit)); // message == "The first quarter has ended with net loss of $200000" 

URL:


 constexpr auto url = make_static_string("http://www.server.com:8080"); constexpr auto p = url.find("://"); constexpr auto protocol = url.prefix<p>(); // protocol == "http" constexpr auto sockaddr = url.suffix<p + 3>(); constexpr auto hp = sockaddr.split<sockaddr.find(':')>(); constexpr auto host = hp.first; // host == "www.server.com" constexpr int port = SSTOI(hp.second); // port == 8080 

:


 constexpr auto str = make_static_string("Hello"); for (size_t i = str.begin(); i != str.end(); ++i) //  std::cout << str[i]; std::cout << std::endl; // Hello for (size_t i = str.rbegin(); i != str.rend(); --i) //  std::cout << str[i]; std::cout << std::endl; // olleH 

рд╕рдВрджрд░реНрдн


, , github


, .


Update


_ss :


 template<typename Char, Char ... Chars> constexpr basic_static_string<Char, sizeof ... (Chars) + 1> operator"" _ss() { return {Chars ..., static_cast<Char>('\0')}; }; 

make_static_string() , :


 constexpr auto hello_world = "Hello"_ss + " World"; if ("Hello" < "World"_ss) { ... } constexpr auto hash = "VeryLongString"_ss.hash(); 

Char char:


 template<typename Char, size_t Size> struct basic_static_string { // ... std::array<const Char, Size> data; }; 

char whar_t, , concat, :


 template<size_t Size> using static_string_t = basic_static_string<char, Size>; template<size_t Size> using static_wstring_t = basic_static_string<wchar_t, Size>; using static_string = basic_static_string<char, 0>; using static_wstring = basic_static_string<wchar_t, 0>; 

"" :


 constexpr auto wide_string = L"WideString"_ss; constexpr int apples = 5; constexpr int oranges = 7; constexpr int fruits = apples + oranges; constexpr auto str3 = static_wstring::concat(L"I have ", ITOSW(apples), L" apples and ", ITOSW(oranges), L" oranges, so I have ", ITOSW(fruits), L" fruits"); static_assert(str3 == L"I have 5 apples and 7 oranges, so I have 12 fruits", ""); std::wcout << str3 << std::endl; 

size(), size() length() , sizeof():


 constexpr auto ss1 = "Hello"_ss; static_assert(ss1.length() == 5, ""); static_assert(ss1.size() == 5, ""); static_assert(sizeof(ss1) == 6, ""); 

github
.


Update 2


AndreySu , :


 #include <iostream> using namespace std; template<typename Char, Char ... Chars> struct static_string{}; template<typename Char, Char ... Chars1, Char ... Chars2> constexpr static_string<Char, Chars1 ..., Chars2 ... > operator+( const static_string<Char, Chars1 ... >& str1, const static_string<Char, Chars2 ... >& str2) { return static_string<Char, Chars1 ..., Chars2 ...>{}; } template<typename Char, Char ch, Char ... Chars> std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& bos, const static_string<Char, ch, Chars ...>& str) { bos << ch << static_string<Char, Chars ... >{}; return bos; } template<typename Char> std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& bos, const static_string<Char>& str) { return bos; } template<typename Char, Char ... Chars> constexpr static_string<Char, Chars ... > operator"" _ss() { return static_string<Char, Chars ... >{}; }; int main() { constexpr auto str1 = "abc"_ss; constexpr auto str2 = "def"_ss; constexpr auto str = str1 + str2 + str1; std::cout << str << std::endl; return 0; } 

, , - .

Source: https://habr.com/ru/post/hi428846/


All Articles