рдЕрд╡рдзрд╛рд░рдгрд╛: рдПрд╕рдЯреАрдбреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╡рд░реНрдЧреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдирд╛


C ++ 20 рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реА рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ рдПрдХ рд▓рдВрдмреЗ рдФрд░ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЪрд░реНрдЪрд╛ рдХрд╛ рд╡рд┐рд╖рдп рд╣реИрдВред рд╡рд░реНрд╖реЛрдВ рд╕реЗ рд╕рдВрдЪрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреА рдЕрдзрд┐рдХрддрд╛ (рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░реАрдп рд╡рд┐рд╢реЗрд╖рдЬреНрдЮреЛрдВ рдХреЗ рднрд╛рд╖рдгреЛрдВ рд╕рд╣рд┐рдд) рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдЕрднреА рднреА рд▓рд╛рдЧреВ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ (рдЬреЛ рдорд╛рдирдХ рдХреЗ рд╕рд╛рде рд░реЛрдЬ рд╕реЛрддреЗ рдирд╣реАрдВ рд╣реИрдВ) рдХреЗ рдмреАрдЪ рднреНрд░рдо рдХреА рд╕реНрдерд┐рддрд┐ рд╣реИ рдХрд┐ C ++ 20 рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ рдХреНрдпрд╛ рд╣реИрдВ рдФрд░ рдХреНрдпрд╛ рд╡реЗ рд╣реИрдВ рдпрджрд┐ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рд╕рдХреНрд╖рдо рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рддреЛ рд╣рдореЗрдВ рдЬрд░реВрд░рдд рд╣реИред рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЧрд▓рддреА рдпрд╣ рд╣реИ рдХрд┐ рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ 15 рд╕рд╛рд▓ рдореЗрдВ рдХреИрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реБрдИрдВ (рдХреЙрдиреНрд╕реЗрдкреНрдЯ рдлреБрд▓ + рдХреЙрдиреНрд╕реЗрдкреНрдЯ рдореИрдк -> рдХреЙрдиреНрд╕реЗрдкреНрдЯ рд▓рд╛рдЗрдЯ), рдФрд░ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдХреНрдпреЛрдВрдХрд┐ рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ (рдЬрд╛рд╡рд╛ / рд╕реА # рдЬреЗрдиреЗрд░рд┐рдХ рд╕реАрдорд╛рдПрдВ, рдЕрдиреБрд╖реНрдард╛рди рд▓рдХреНрд╖рдг) рдореЗрдВ рд╕рдорд╛рди рдЯреВрд▓ рдХреЗ рд╡рд┐рдкрд░реАрдд рд╣реИрдВред ..)ред


C ++ рд░реВрд╕ 2019 рд╕рдореНрдореЗрд▓рди рд╕реЗ ReSharper C ++ рдЯреАрдо рд╕реЗ рдПрдВрдбреНрд░реА рдбреЗрд╡рд┐рдбреЛрд╡ рдХреА рдПрдХ рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рдХрдЯ - рд╡реАрдбрд┐рдпреЛ рдФрд░ рдЯреНрд░рд╛рдВрд╕рдХреНрд░рд┐рдкреНрдЯ рдХреЗ рддрд╣рддред рдПрдВрдбреНрд░реА рдиреЗ C ++ 20 рдХреЗ рдЕрд╡рдзрд╛рд░рдгрд╛-рд╕рдВрдмрдВрдзреА рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдХреА рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕рдореАрдХреНрд╖рд╛ рдХреА, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдЙрдиреНрд╣реЛрдВрдиреЗ C ++ 17 рдФрд░ C ++ 20 рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реБрдП STL рдХреЗ рдХреБрдЫ рд╡рд░реНрдЧреЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЬрд╛рдВрдЪ рдХреАред рдЖрдЧреЗ рдХреА рдХрд╣рд╛рдиреА рдЙрд╕рдХреА рдУрд░ рд╕реЗ рд╣реИред



рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВред рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рдЬрдЯрд┐рд▓ рдФрд░ рд╡реНрдпрд╛рдкрдХ рд╡рд┐рд╖рдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рд░рд┐рдкреЛрд░реНрдЯ рдХреА рддреИрдпрд╛рд░реА рдХрд░рддреЗ рд╕рдордп, рдореИрдВ рдХреБрдЫ рдореБрд╢реНрдХрд┐рд▓ рдореЗрдВ рдерд╛ред рдореИрдВрдиреЗ C ++ рд╕рдореБрджрд╛рдп рдХреЗ рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рд╡рдХреНрддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдЖрдВрджреНрд░реЗрдИ рдЕрд▓реЗрдХреНрдЬреЗрдВрдбреНрд░реЗрд╕реНрдХреБ рдХреЗ рдЕрдиреБрднрд╡ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред


рдирд╡рдВрдмрд░ 2018 рдореЗрдВ, рдореАрдЯрд┐рдВрдЧ рд╕реА ++ рдХреЗ рдЙрджреНрдШрд╛рдЯрди рдкрд░ рдмреЛрд▓рддреЗ рд╣реБрдП, рдЖрдВрджреНрд░реЗрдИ рдиреЗ рджрд░реНрд╢рдХреЛрдВ рд╕реЗ рдкреВрдЫрд╛ рдХрд┐ рд╕реА ++ рдХреА рдЕрдЧрд▓реА рдмрдбрд╝реА рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреНрдпрд╛ рд╣реЛрдЧреА:


  • рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ
  • metaclasses
  • рдпрд╛ рдЖрддреНрдордирд┐рд░реАрдХреНрд╖рдг?

рдЖрдЗрдП рдЗрд╕ рдкреНрд░рд╢реНрди рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ C ++ рдореЗрдВ рдЕрдЧрд▓реА рдмрдбрд╝реА рд╡рд┐рд╢реЗрд╖рддрд╛ рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ рд╣реЛрдВрдЧреА?


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


рдЬрдм рд╣рдо C ++ 20 рдореЗрдВ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд╣рдорд╛рд░рд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ? рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдкрд░ рдХрдо рд╕реЗ рдХрдо 2003 рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИ, рдФрд░ рдЗрд╕ рд╕рдордп рдХреЗ рджреМрд░рд╛рди рдпрд╣ рдмрд╣реБрдд рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реА рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ C ++ 20 рдореЗрдВ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╕рдВрдмрдВрдзреА рдХреМрди-рдХреМрди рд╕реА рдирдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рджрд┐рдЦрд╛рдИ рджреАрдВред


"рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ" рдирд╛рдордХ рдПрдХ рдирдИ рдЗрдХрд╛рдИ рдХреЛ concept рдХреАрд╡рд░реНрдб рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рдПрдХ рд╡рд┐рдзреЗрдп рд╣реИред рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 template <typename T> concept NoThrowDefaultConstructible = noexept(T{}); template <typename From, typename To> concept Assignable = std::is_assignable_v<From, To> 

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


 template<int I> concept Even = I % 2 == 0; 

рд▓реЗрдХрд┐рди рдпрд╣ рдареЗрда рдФрд░ atypical рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдорд┐рд╢реНрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЫреЛрдЯрд╛ рдХрд╣рддреЗ рд╣реИрдВ рдпрджрд┐ рдЗрд╕рдХрд╛ рдЖрдХрд╛рд░ рдФрд░ рд╕рдВрд░реЗрдЦрдг рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛рдУрдВ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ:


 template<typename T, size_t MaxSize, size_t MaxAlign> concept Small = sizeof(T) <= MaxSize && alignof(T) <= MaxAlign; 

рд╢рд╛рдпрдж, рдпрд╣ рдЕрднреА рддрдХ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рднрд╛рд╖рд╛ рдореЗрдВ рдПрдХ рдирдИ рдЗрдХрд╛рдИ рдХреЛ constexpr bool рдХреНрдпреЛрдВ рд╣реИ, рдФрд░ рдХреНрдпреЛрдВ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╕рд┐рд░реНрдл рдПрдХ constexpr bool рд╡реИрд░рд┐рдПрдмрд▓ рдирд╣реАрдВ рд╣реИред


 //  `concept`    ? #define concept constexpr bool 

рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ?


рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, constexpr bool рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреА рддрд░рд╣, рд╕рдВрдХрд▓рди-рд╕рдордп рдореЗрдВ рдЬрд╣рд╛рдБ рднреА рдЖрдкрдХреЛ рдмреВрд▓рд┐рдпрди рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, static_assert рдЕрдВрджрд░ рдпрд╛ noexcept рдЕрдВрджрд░
рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ:


 // bool expression evaluated in compile-time static_assert(Assignable<float, int>); template<typename T> void test() noexcept(NothrowDefaultConstructible<T>) { T t; ... } 

рджреВрд╕рд░реА рдмрд╛рдд, рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╕рдордп typename рдпрд╛ class рдХреАрд╡рд░реНрдб рдХреЗ рдмрдЬрд╛рдп рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рд╕рд░рд▓ optional рд╡рд░реНрдЧ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ рдЬреЛ рдмрд╕ рдмреВрд▓реАрдпрди рдзреНрд╡рдЬ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЛ initialized рдФрд░ рдорд╛рдиреЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ред рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рдРрд╕реЗ optional рдХреЗрд╡рд▓ рддреБрдЪреНрдЫ рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдпрд╣рд╛рдБ Trivial рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЬрдм рд╣рдо рдХреБрдЫ рдЧреИрд░-рддреБрдЪреНрдЫ рд╕реЗ рддрд╛рддреНрдХрд╛рд▓рд┐рдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, std::string , рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреА:


 //  type-parameter-key (class, typename) template<Trivial T> class simple_optional { T value; bool initialized = false; ... }; 

рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрдкрдиреА рдХрдХреНрд╖рд╛ рдХреЛ рдЫреЛрдЯреЗ рдмрдлрд░ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд Size рдФрд░ Alignment рд╕рд╛рде SB рд╕рдВрд░рдЪрдирд╛ (рдЫреЛрдЯреЗ рдмрдлрд░) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ, рд╣рдо SB рдФрд░ рдвреЗрд░ рдкрд░ рд╕реВрдЪрдХ рд╕реЗ рдпреВрдирд┐рдпрди рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗред рдФрд░ рдЕрдм, рдпрджрд┐ рдПрдХ рдЫреЛрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ SB рдореЗрдВ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдПрдХ рдкреНрд░рдХрд╛рд░ рдЫреЛрдЯрд╛ рд╣реИ, рд╣рдо рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ Small рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИред Small рдЕрд╡рдзрд╛рд░рдгрд╛ рдореЗрдВ 3 рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд▓рд┐рдП рдЧрдП: рд╣рдордиреЗ рджреЛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛, рдФрд░ рд╣рдореЗрдВ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдорд┐рд▓рд╛:


 //   class any { struct SB { static constexpr size_t Size = ...; static constexpr size_t Alignment = ...; aligned_storage_t<Size, Alignment> storage; }; union { SB sb; void* handle; }; template<Small<SB::Size, SB::Alignment> T> any(T const & t) : sb(...) ... }; 

рдПрдХ рдЫреЛрдЯрд╛ рд░рд┐рдХреЙрд░реНрдб рд╣реИред рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдирд╛рдо рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рд╕рдВрднрд╡рддрдГ auto рд╕реЗ рдкрд╣рд▓реЗ рдХреБрдЫ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рдеред рдкрд┐рдЫрд▓рд╛ рдЙрджрд╛рд╣рд░рдг рдЗрд╕ рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ:


 // Terse syntax (  auto) class any { struct SB { static constexpr size_t Size = ...; static constexpr size_t Alignment = ...; aligned_storage_t<Size, Alignment> storage; }; union { SB sb; void* handle; }; any(Small<SB::Size, SB::Alignment> auto const & t) : sb(...) ... }; 

рд╢рд╛рдпрдж, рдХрд┐рд╕реА рднреА рдЬрдЧрд╣ рдЬрд╣рд╛рдВ рд╣рдо auto рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдЕрдм рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рдордиреЗ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдирд╛рдо рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред


get_handle рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ, рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдХреБрдЫ handle рд▓реМрдЯрд╛рддрд╛ рд╣реИред
рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЫреЛрдЯреА рд╡рд╕реНрддреБрдПрдВ рдЦреБрдж рдХреЛ handle , рдФрд░ рдмрдбрд╝реА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП, рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХ handle ред рдЪреВрдБрдХрд┐ рд╣рдорд╛рд░реА рджреЛ рд╢рд╛рдЦрд╛рдПрдБ рд╣реИрдВ if constexpr рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ if constexpr рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рди рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рд╕рдВрдХрд▓рдХ рд╕реЗ рдЗрд╕рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдмрд╕ auto , рддреЛ рд╣рдо рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдЦреЛ рджреЗрдВрдЧреЗ рдХрд┐ рд╕рдВрдХреЗрддрд┐рдд рдореВрд▓реНрдп рдЫреЛрдЯрд╛ рд╣реИ, рдпрд╣ рд╕реВрдЪрдХ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ:


 //Terse syntax (  auto) template<typename T> concept LEPtr = Small<T, sizeof(void *), alignof(void *)>; template<typename T> auto get_handle(T& object) { if constexpr (LEPtr<T>) return object; else return &object; } 

C ++ 20 рдореЗрдВ, рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рд▓рд┐рдЦрдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ рдХрд┐ рдпрд╣ рд╕рд┐рд░реНрдл auto рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╕реАрдорд┐рдд auto :


 // Terse syntax (  auto) template<typename T> concept LEPtr = Small<T, sizeof(void *), alignof(void *)>; template<typename T> LEPtr auto get_handle(T &object) { if constexpr (LEPtr<T>) return object; else return &object; } 

рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ


рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐'рдУрд╡ рдХрд╛ рдПрдХ рдкреВрд░рд╛ рдкрд░рд┐рд╡рд╛рд░ рд╣реИ, рдЙрдирдореЗрдВ рд╕реЗ рд╕рднреА рдЯрд╛рдЗрдк bool рдФрд░ рд╕рдВрдХрд▓рди-рд╕рдордп рдореЗрдВ рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред рд╡реЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрдпрд╛рдиреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред


Constructible рдЙрджрд╛рд╣рд░рдгред рдЬреЛ рд▓реЛрдЧ рдореЗрд░реА рдкрд┐рдЫрд▓реА рд░рд┐рдкреЛрд░реНрдЯ рдореЗрдВ рдереЗ, рд╡реЗ рдЙрд╕реЗ рджреЗрдЦ рдЪреБрдХреЗ рд╣реИрдВ:


 template<typename T, typename... Args> concept Constructible = requires(Args... args) { T{args...} }; 

рдФрд░ рддреБрд▓рдирд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдЙрджрд╛рд╣рд░рдгред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЯрд╛рдЗрдк T Comparable рдпрджрд┐ рдЯрд╛рдЗрдк T рдХреА рджреЛ рд╡рд╕реНрддреБрдУрдВ рдХреА рддреБрд▓рдирд╛ "рдХрдо" рдСрдкрд░реЗрдЯрд░ рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдо bool рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рддреАрд░ рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рдж рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ bool рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдирд╣реАрдВ рдХрд┐ рдпрд╣ bool рдмрд░рд╛рдмрд░ рд╣реИ:


 template<typename T> concept Comparable = requires(T const & a, T const & b) { {a < b} -> bool; }; 

рд╣рдордиреЗ рдЬреЛ рдЬрд╛рдВрдЪ рдХреА рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рдПрдХ рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред


рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ Comparable рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИ, рдЪрд▓реЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдорд╛рди RandomAccessIterator рдХрд┐ RandomAccessIterator рдПрдХ BidirectionalIterator рдФрд░ рдХреБрдЫ рдЕрдиреНрдп рдЧреБрдг рд╣реИрдВред рдЗрд╕рдХреЗ рд╕рд╛рде, рд╣рдо Sortable рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред Range рдХреЛ RandomAccess рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрджрд┐ рдЗрд╕рдХреЗ RandomAccess рдПрд╕реЗрдЯрд░реНрд╕ рдФрд░ рдЙрд╕рдХреЗ рддрддреНрд╡реЛрдВ рдХреА рддреБрд▓рдирд╛ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдФрд░ рдЕрдм рд╣рдо рдПрдХ sort рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рди рдХреЗрд╡рд▓ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ sort Sortable Range :


 // concepts,    ++20 template<typename Iterator> concept RandomAccessIterator = BidirectionalIterator<Iterator> && ...; template<typename R> concept Sortable = RandomAccessIterator<Iterator<R>> && Comparable<ValueType<R>>; template<Sortable Range> void sort(Range &) {...} 

рдЕрдм, рдпрджрд┐ рд╣рдо рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЙрд╕ рдЪреАрдЬрд╝ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ Sortable рдХрд░рдиреЗ Sortable рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдХрдВрдкрд╛рдЗрд▓рд░ рд╕реЗ рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕рдВрджреЗрд╢ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫрд╛, SFINAE- рдЕрдиреБрдХреВрд▓ рддреНрд░реБрдЯрд┐ рдорд┐рд▓реЗрдЧреАред рдЖрдЗрдП рдПрдХ std::list 'рдпрд╛ рд╡реЗрдХреНрдЯрд░ рдХреЗ рддрддреНрд╡реЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ рдЬреЛ рддреБрд▓рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 //concepts,    ++20,  struct X {}; void test() { vector<int> vi; sort(vi); // OK list <int> li; sort(li); // Fail, list<int>::iterator is not random access vector< X > vx; sort(vx); // Fail, X is not Comparable } 

рдХреНрдпрд╛ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдпрд╛ рдХреБрдЫ рд╕рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рдорд╛рди рдЙрджрд╛рд╣рд░рдг рджреЗрдЦрд╛ рд╣реИ? рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрдИ рдмрд╛рд░ рджреЗрдЦрд╛ рд╣реИред рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рдХрд╣реВрдВ рддреЛ рдЗрд╕рдиреЗ рдореБрдЭреЗ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рд╕рдордЭрд╛ред рдХреНрдпрд╛ рд╣рдореЗрдВ рднрд╛рд╖рд╛ рдореЗрдВ рдЗрддрдиреА рдирдИ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдмрд╛рдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрдЧрд░ рд╣рдо рдЗрд╕реЗ C ++ 17 рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?


 //concepts,    ++17 #define concept constexpr bool template<typename T> concept Comparable = is_convertible_v< decltype(declval<T const &>() < declval<T const &>()), bool >; template<typename Iterator> concept RandomAccessIterator = BidirectionalIterator<Iterator> && ...; template<typename R> concept Sortable = RandomAccessIterator<Iterator<R>> && Comparable<ValueType<R>>; template<typename Range, typename = enable_if_t<Sortable<Range>>> void sort(Range &) { ... } 

рдореИрдВрдиреЗ concept рдореИрдХреНрд░реЛ рдХреЗ concept рдХреАрд╡рд░реНрдб concept рджрд░реНрдЬ рдХреА, рдФрд░ Comparable рдЗрд╕ рддрд░рд╣ Comparable рдлрд┐рд░ Comparable рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рдереЛрдбрд╝рд╛ рдмрджрд╕реВрд░рдд рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕рдВрдХреЗрдд рд╣реИ рдХрд┐ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдЙрдкрдпреЛрдЧреА рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЪреАрдЬ рд╣реИред рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ Sortable рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдФрд░ enable_if рдХрд╛ рдЙрдкрдпреЛрдЧ enable_if рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдХрд┐ sort рдлрд╝рдВрдХреНрд╢рди Sortable Range рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред


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


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


рдЦрдВрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ


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


 // requires-clause template<typename R> concept Sortable = RandomAccessIterator<Iterator<R>> && Comparable<ValueType<R>>; template<Sortable Range> void sort(Range &) { ... } 

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


 template<typename R> concept Sortable = RandomAccessIterator<Iterator<R>> && Comparable<ValueType<R>>; template<typename Range> requires Sortable<Range> void sort(Range &) { ... } 

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


 //template<typename R> concept Sortable // = RandomAccessIterator<Iterator<R>> && Comparable<ValueType<R>>; template<typename Range> requires RandomAccessIterator<Iterator<Range>> && Comparable<ValueType<Range>>; void sort(Range &) { ... } 

рдЕрд╡рдзрд╛рд░рдгрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреА рд╕рд╛рд░рд╛рдВрд╢ рд╕реВрдЪреА


C ++ 20 рдореЗрдВ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдХреА рд╕реВрдЪреА рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИред рдЗрд╕ рд╕реВрдЪреА рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдореЗрд░реЗ рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдХрд░рдХреЗ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:


  • рдирдИ рдЗрдХрд╛рдИ concept ред рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрддрд┐рд░рд┐рдХреНрдд рд╢рдмреНрджрд╛рд░реНрде рдХреЗ рд╕рд╛рде constexpr bool рдЪрд░ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдХреЗ concept рд╕рд╛рд░ рдХреЗ рдмрд┐рдирд╛ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред
  • рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ред рдмреЗрд╢рдХ, рдпрд╣ рд╕реБрдЦрдж рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рд░реНрдл рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИред рдпрджрд┐ C ++ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЦрд░рд╛рдм рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реЗ рдбрд░рддреЗ рдереЗ, рддреЛ рд╡реЗ рдбрд░ рд╕реЗ рдмрд╣реБрдд рдкрд╣рд▓реЗ рд╣реА рдорд░ рдЬрд╛рддреЗ рдереЗред
  • рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫреА рдмрд╛рдд рд╣реИ, рдФрд░ рдпрд╣ рди рдХреЗрд╡рд▓ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИред
  • рдХреНрд▓реЙрдЬ рдХреЗ рд▓рд┐рдП рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рдореВрд▓реНрдп рд╣реИ, рдпрд╣ рдЖрдкрдХреЛ SFINAE рдФрд░ C ++ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреЗ рдЕрдиреНрдп рдкреНрд░рд╕рд┐рджреНрдз рднрдпрд╛рд╡рд╣рддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдЕрдзрд┐рдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ


рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдХреНрд▓реЙрдЬрд╝ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВ, рдХреБрдЫ рд╢рдмреНрджреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЙрдиреНрд╣реЗрдВ рди рдХреЗрд╡рд▓ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкреБрд░рд╛рдиреЗ рд╕рдордп рд╕реЗ, Microsoft рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди __if_exists - __if_not_exists ред рдпрд╣ рдПрдХ рдирд╛рдо рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдХрд▓рди-рд╕рдордп рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░, рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдПрдХ рдХреЛрдб рдмреНрд▓реЙрдХ рдХреЗ рд╕рдВрдХрд▓рди рдХреЛ рд╕рдХреНрд╖рдо рдпрд╛ рдЕрдХреНрд╖рдо рдХрд░рддрд╛ рд╣реИред рдФрд░ рдХреЛрдб рдмреЗрд╕ рдореЗрдВ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдореИрдВрдиреЗ рдХрдИ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдерд╛, рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдерд╛ред рдПрдХ рдлрд╝рдВрдХреНрд╢рди f() , рдпрд╣ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдмрд┐рдВрджреБ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рдмрд┐рдВрджреБ рд╕реЗ рдКрдВрдЪрд╛рдИ рд▓реЗрддрд╛ рд╣реИред рдЗрд╕реЗ рддреАрди-рдЖрдпрд╛рдореА рдпрд╛ рджреЛ-рдЖрдпрд╛рдореА рдмрд┐рдВрджреБ рджреНрд╡рд╛рд░рд╛ рддреНрд╡рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рддреНрд░рд┐-рдЖрдпрд╛рдореА рдХреЗ рд▓рд┐рдП, рд╣рдо z рд╕рдордиреНрд╡рдп рдХреЛ рдКрдВрдЪрд╛рдИ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддреЗ рд╣реИрдВ, рджреЛ-рдЖрдпрд╛рдореА рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рддрд╣ рд╕реЗрдВрд╕рд░ рдХреА рдУрд░ рдореБрдбрд╝рддреЗ рд╣реИрдВред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 struct Point2 { float x, y; }; struct Point3 { float x, y, z; }; template<typename Point> void f(Point const & p) { float h; __if_exists(Point::z) { h = pz; } __if_not_exists(Point::z) { h = sensor.get_height(p); } } 

C ++ 20 рдореЗрдВ, рд╣рдо рдорд╛рдирдХ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рдХ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдмрджрддрд░ рдирд╣реАрдВ рд╣реЛ рдЧрдпрд╛ рд╣реИ:


 struct Point2 { float x, y; }; struct Point3 { float x, y, z; }; template<typename Point> void f(Point const & p) { float h; if constexpr(requires { Point::z; }) h = pz; else h = sensor.get_height(p); } 

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


рдЖрдЗрдП рдПрдХ Sizable рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ size рдЬреЛ size_t рджреЗрддрд╛ рд╣реИред рд╣рдо рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ vector<int> Sizable , рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ static_assert ред рдХреНрдпрд╛ рдЖрдк рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╕реЗ рдЧрд▓рддреА рдХреНрдпреЛрдВ рд╣реБрдИ? рдпрд╣ рдХреЛрдб рд╕рдВрдХрд▓рди рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ?


 template<typename Container> concept Sizable = requires(Container const & c) { c.size() -> size_t; }; static_assert(Sizable<vector<int>>); // Fail 

рдореИрдВ рдЖрдкрдХреЛ рд╡рд╣ рдХреЛрдб рджрд┐рдЦрд╛рддрд╛ рд╣реВрдВ рдЬреЛ рд╕рдВрдХрд▓рди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ X рд╡рд░реНрдЧ Sizable рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИред рдЕрдм рдЖрдк рд╕рдордЭ рдЧрдП рд╣реИрдВ рдХрд┐ рд╣рдореЗрдВ рдХреНрдпрд╛ рд╕рдорд╕реНрдпрд╛ рд╣реИ?


 struct X { struct Inner { int size_t; }; Inner* size() const; }; static_assert(Sizable<X>); // OK 

рдореБрдЭреЗ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд┐рдВрдЧ рдХреЛрдб рдареАрдХ рдХрд░рдиреЗ рджреЗрдВред рдмрд╛рдИрдВ рдУрд░, рдХреЛрдб рд░рдВрдЧреАрди рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рдЪрд╛рд╣реВрдВрдЧрд╛ред рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЗрд╕реЗ рджрд╛рдИрдВ рдУрд░ рдЪрд┐рддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:



рджреЗрдЦреЗрдВ, рддреАрд░ рдХреЗ рдмрд╛рдж рдЦрдбрд╝реЗ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ size_t рдХрд╛ рд░рдВрдЧ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ? рдореИрдВ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реЛ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рд░реНрдл рд╡рд╣ рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдПрдХреНрд╕реЗрд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЬреЛ рдХреБрдЫ рднреА рд╣реИ, рд╡рд╣ рдПрдХ рдмрдбрд╝реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕рдХреА рд╢реБрджреНрдзрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред рдЯрд╛рдЗрдк X , рд╣рд╛рдБ, рдпрд╣ рдПрдХ рд╡реИрдз рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ; vector<int> , рдирд╣реАрдВред рдЬреЛ рд╣рдо рдЪрд╛рд╣рддреЗ рдереЗ рдЙрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдмреНрд░реЗрд╕рд┐рдЬрд╝ рдореЗрдВ рд▓реЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 template<typename Container> concept Sizable = requires(Container const & c) { {c.size()} -> size_t; }; static_assert(Sizable<vector<int>>); // OK struct X { struct Inner { int size_t; }; Inner* size() const; }; static_assert(Sizable<X>); // Fail 

рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рдордЬреЗрджрд╛рд░ рдЙрджрд╛рд╣рд░рдг рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЖрдкрдХреЛ рдмрд╕ рд╕рд╛рд╡рдзрд╛рди рд░рд╣рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред


рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдг


рдЬреЛрдбрд╝реА рд╡рд░реНрдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдореИрдВ рдХреБрдЫ рдПрд╕рдЯреАрдПрд▓ рдЕрдВрд╢реЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реВрдВрдЧрд╛ рдЬрд┐рдиреНрд╣реЗрдВ C ++ 17 рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдмреЛрдЭрд┐рд▓ рднреАред
рдФрд░ рдлрд┐рд░ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдХреИрд╕реЗ C ++ 20 рдореЗрдВ рд╣рдо рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


pair рдХреНрд▓рд╛рд╕ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред
рдпрд╣ рдПрдХ рдмрд╣реБрдд рдкреБрд░рд╛рдирд╛ рд╡рд░реНрдЧ рд╣реИ, рдпрд╣ рдЕрднреА рднреА C ++ 98 рдореЗрдВ рд╣реИред
рдЗрд╕рдореЗрдВ рдХреЛрдИ рдЬрдЯрд┐рд▓ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП
рдореИрдВ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рдЙрд╕рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗред
рдпрд╣, рдореЗрд░реЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдЗрд╕ рдкрд░ рд▓рдЧрднрдЧ рд╕рдорд╛рдкреНрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:


 template<typename F, typename S> struct pair { F f; S s; ... }; 

рд▓реЗрдХрд┐рди, cppreference рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдбрд┐рдЬрд╛рдЗрдирд░реЛрдВ pair рдПрдХ pair рдХреЗрд╡рд▓ 8 рдЯреБрдХрдбрд╝реЗ рд╣реЛрддреЗ рд╣реИрдВред
рдФрд░ рдпрджрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рдПрд╕рдЯреАрдПрд▓ рдореЗрдВ, рддреЛ pair рд╡рд░реНрдЧ рдХреЗ 15 рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрдИ рд╣реЛрдВрдЧреЗред рд╣рдо рдЗрд╕ рд╕рд╛рд░реА рд╢рдХреНрддрд┐ рдХреЛ рдирд╣реАрдВ рджреЗрдЦреЗрдВрдЧреЗ рдФрд░ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рддрдХ рд╕реАрдорд┐рдд рд░рдЦреЗрдВрдЧреЗред


рдРрд╕рд╛ рд▓рдЧреЗрдЧрд╛ рдХрд┐ рдпрд╣ рдХреБрдЫ рдЬрдЯрд┐рд▓ рд╣реИ? рд╢реБрд░реБрдЖрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИред рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд░ pair рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рддрд░реНрдХ рдПрдХ рддреБрдЪреНрдЫ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдерд╛, int рдХрд╣рдирд╛ рд╣реИ, рддреЛ pair рд╡рд░реНрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рд╢реВрдиреНрдп рдкрд░ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдпрд╣ рдПрдХрддрд░рдлрд╛ рдирд╣реАрдВ рд░рд╣рд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ рдлрд╝реАрд▓реНрдб f (рдкреНрд░рдердо) рдФрд░ s (рджреВрд╕рд░рд╛) рдХреЗ рд▓рд┐рдП рдореВрд▓реНрдп-рдЖрд░рдВрднреАрдХрд░рдг рдХрд╣рддрд╛ рд╣реИред


 template<typename F, typename S> struct pair { F f; S s; pair() : f() , s() {} }; 

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


 struct A { A(int); }; pair<int, A> a2; // must fail pair<int, A> a1; { 1, 2 }; // must be OK 

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕реЗ SFINAE рддрдХ рд╕реАрдорд┐рдд рдХрд░реЗрдВред
рдкрд╣рд▓рд╛ рд╡рд┐рдЪрд╛рд░ рдЬреЛ рдорди рдореЗрдВ рдЖрддрд╛ рд╣реИ рд╡рд╣ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдЗрд╕ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдХреЗрд╡рд▓ рддрднреА рдЕрдиреБрдорддрд┐ рджреА рдЬрд╛рдП рдЬрдм f рдФрд░ s is_default_constructable :


 template<typename F, typename S> struct pair { F f; S s; template<typename = enable_if_t<conjunction_v< is_default_constructible<F>, // not dependent is_default_constructible<S> >>> pair() : f(), s() {} }; 

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


рдЗрд╕реЗ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдЗрд╕ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЕрдзрд┐рдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЗрди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░реНрд╕ рдкрд░ enable_if_t рдХреЛ рдХрдВрдбреАрд╢рди рдХрд░реЗрдВ:


 template<typename F, typename S> struct pair { F f; S s; template<typename T = F, typename U = S, typename = enable_if_t<conjunction_v< is_default_constructible<T>, is_default_constructible<U> >>> pair() : f(), s() {} }; 

рд╕реНрдерд┐рддрд┐ рдХрд╛рдлреА рдордЬреЗрджрд╛рд░ рд╣реИред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ T рдФрд░ U рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред C ++ рдореЗрдВ, рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдирд╣реАрдВ рд╣реИ, рд╡реЗ рд╕рдВрдХрд▓рдХ рджреНрд╡рд╛рд░рд╛ рдЖрдЙрдЯрдкреБрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реАрдВ рдирд╣реАрдВ рд╣реИред рд╡реЗ рдХреЗрд╡рд▓ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗ рдЖ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣реА рд╣реИ, рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдпрд╣ рдХреЛрдб рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХреЛрдб рд╕реЗ рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рдВрдХрд▓рдХ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдпрд╣ рдорд╛рдиреНрдп рд╣реИ, рд▓реЗрдХрд┐рди рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдирд╣реАрдВред


рд╣рдордиреЗ рдЕрдкрдиреА рдкрд╣рд▓реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рд╣рдо рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдереЛрдбрд╝рд╛ рдФрд░ рд╕реВрдХреНрд╖реНрдоред рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧ B , рдФрд░ рд╣рдо pair<int, B> рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ pair<int, B> :


 struct B { explicit B(); }; pair<int, B> p = {}; 

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


рдкреНрд░рд╢реНрди: рдХреНрдпрд╛ рд╣рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдЬреЛрдбрд╝реА рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ? рд╕реА ++ 17 рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реЛрд▓реЛрдорди рд╕рдорд╛рдзрд╛рди рд╣реИ: рдЖрдЗрдП рдРрд╕реЗ рдФрд░ рдРрд╕реЗ рджреЛрдиреЛрдВ рдХреЛ рд▓рд┐рдЦреЗрдВред


 template<typename F, typename S> struct pair { F f; S s; template<typename T = F, typename U = S, typename = enable_if_t<conjunction_v< is_default_constructible<T>, is_default_constructible<U>, is_implicity_default_constructible<T>, is_implicity_default_constructible<U> >>> pair() : f(), s() {} template<...> explicit pair() : f(), s() {} }; 

рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реИрдВ:


  • рдЬрдм рддрддреНрд╡ рдореВрд▓ рд░реВрдк рд╕реЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрдорд╛рдг рдпреЛрдЧреНрдп рд╣реЛрддреЗ рд╣реИрдВ рддреЛ рд╣рдо рдЙрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП SFINAE рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рдХрд╛рдЯ рджреЗрдВрдЧреЗ;
  • рдФрд░ рд╡рд┐рдкрд░реАрдд рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░рд╛ред

рд╡реИрд╕реЗ, C ++ 17 рдореЗрдВ рдЯрд╛рдЗрдк рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП is_implicitly_default_constructible рд╣реИ, рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЛ рдЬрд╛рдирддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ SFINAE рдХреЗ рдмрд┐рдирд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рдЬрд╛рдирддрд╛:


 template<typrname T> true_type test(T, int); template<typrname T> false_type test(int, ...); template<typrname T> using is_implicity_default_constructible = decltype(test<T>({}, 0)); 

рдпрджрд┐ рд╣рдо рдЕрдм pair <int, B> рдмрдирд╛рдиреЗ pair <int, B> рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ pair <int, B> , рддреЛ рд╣рдореЗрдВ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЪрд╛рд╣рддреЗ рдереЗ:


 template<..., typename = enable_if_t<conjuction_v< is_default_constructible<T>, is_default_constructible<U>, is_implicity_default_constructible<T>, is_implicity_default_constructible<U> >>> ... pair<int, B> p = {}; ... candidate template ignored: requirement 'conjunction_v< is_default_constructible<int>, is_default_constructible<B>, is_implicity_default_constructible<int>, is_implicity_default_constructible<B> >' was not satisfied [with T=int, U=B] 

рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрдВрдкрд╛рдЗрд▓рд░реЛрдВ рдореЗрдВ, рдпрд╣ рддреНрд░реБрдЯрд┐ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбрд┐рдЧреНрд░реА рдХреА рд╕рдордЭрджрд╛рд░реА рдХреА рд╣реЛрдЧреАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ Microsoft рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╣рддрд╛ рд╣реИ: "рдЦрд╛рд▓реА рдкреЗрдЯ рдмреНрд░реИрдХреЗрдЯ рд╕реЗ рдПрдХ рдЬреЛрдбрд╝реА <int, B> рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛ред" рдЬреАрд╕реАрд╕реА рдФрд░ рдХреНрд▓реИрдВрдЧ рдЗрд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ: "рд╣рдордиреЗ рдЗрд╕ рддрд░рд╣ рдХреЗ рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдирд╣реАрдВ рдЖрдпрд╛," рдФрд░ рд╡реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдХрд╛рд░рдг рдХрд╣реЗрдВрдЧреЗред


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


рдЬреАрд╕реАрд╕реА рдХрд╛ рдХрд╣рдирд╛ рд╣реИ: "рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╡рд┐рдлрд▓ рд╣реЛ рдЧрдпрд╛, enable_if<false> рдЕрдВрджрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА - рдЦреЗрдж рдирд╣реАрдВ рдорд┐рд▓рд╛ред"


рдХреНрд▓реИрдВрдЧ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓рд╛ рдорд╛рдирддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╡рд╣ рдмрд╣реБрдд рд╣реА рд╢рд╛рдВрдд рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред рдпрджрд┐ рд╣рдо рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреЗ enable_if рдореВрд▓реНрдпрд╛рдВрдХрди false рд╕рдордп false рд╣реЛ enable_if рд╣реИрдВ, рддреЛ рд╡рд╣ рд▓рд┐рдЦрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рд╣реИред


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


рдЕрдЧрд░ рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЪрд╛рд░ рдореЗрдВ enable_if рдХреЛ рддреЛрдбрд╝рддреЗ рд╣реИрдВ рддреЛ рдЗрд╕реЗ рджреВрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 template<..., typename = enable_if_t<is_default_constructible<T>::value>>, typename = enable_if_t<is_default_constructible<U>::value>>, typename = enable_if_t<is_implicity_default_constructible<T>::value>>, typename = enable_if_t<is_implicity_default_constructible<U>::value>> > ... 

рдЕрдм, рдЬрдм рд╣рдо рдПрдХ рдЬреЛрдбрд╝реА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рд╕рдВрджреЗрд╢ рдорд┐рд▓рддрд╛ рд╣реИ рдХрд┐ рдРрд╕рд╛ рдХреЛрдИ рдЙрдореНрдореАрджрд╡рд╛рд░ рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рдХрд╛рд░ рд╡рд┐рд╢реЗрд╖рддрд╛ is_implicitly_default_constructable рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ:


 pair<int, B> p = {}; // candidate template ignored: requirement 'is_implicity_default_constructible<B>::value' was not satisfied with... 

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


C ++ 20 рд╣рдореЗрдВ рдХреИрд╕реЗ рдорджрдж рдХрд░реЗрдЧрд╛? рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕реЗ рдХреНрд▓реЙрдЬ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдХрд░ рдкреИрдЯрд░реНрди рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдПрдВред рд╣рдордиреЗ рдкрд╣рд▓реЗ enable_if рдЕрдВрджрд░ рдХреНрдпрд╛ рд▓рд┐рдЦрд╛ рдерд╛, рдЕрдм рд╣рдо рдХреНрд▓реЙрдЬ рддрд░реНрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдЕрдВрджрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


 template<typename F, typename S> struct pair { F f; S s; pair() requires DefaultConstructible<F> && DefaultConstructible<S> && ImplicitlyDefaultConstructible<F> && ImplicitlyDefaultConstructible<S> : f(), s() {} explicit pair() ... }; 

ImplicitlyDefaultConstructible рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдРрд╕реА рдЕрдЪреНрдЫреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЕрдВрджрд░ рд▓рдЧрднрдЧ рд╡рд┐рднрд┐рдиреНрди рдЖрдХрд╛рд░реЛрдВ рдХреЗ рдХреЗрд╡рд▓ рдХреЛрд╖реНрдардХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 template<typename T> concept ImplicitlyDefaultConstructible = requires { [] (T) {} ({}); }; 

T ImplicitlyDefaultConstructible , , T . , , SFINAE.


C++20: (conditional) explicit ( noexcept ). explicit . , explicit .


 template<typename F, typename S> struct pair { F f; S s; explicit(!ImplicityDefaultConstructible<F> || !ImplicityDefaultConstructible<S>) pair() requires DefaultConstructible<F> && DefaultConstructible<S> : f(), s() {} }; 

, . , DefaultConstructible , explicit , explicit .


Optional C++17


Optional . , .


. ? , C++ :


 enum Option<T> { None, Some(t) } 

:


 class Optional<T> { final T value; Optional() {this.value = null; } Optional(T value) {this.value = value; } } 

C++: null , value-?


C++ . initialized storage , , . T , optional T , C++ memory model.


 template<typename T> class optional { bool initialized; aligned_storage_t<sizeof(T), alignof(T)> storage; ... 

, . : optional , optional . :


  ... T & get() & { return reinterpret_cast<T &>(storage); } T const & get() const & { return reinterpret_cast<T const &>(storage); } T && get() && { return move(get()); } optional() noexcept : initialized(false) {} optional(T const & value) noexcept(NothrowCopyConstructible<T>) : initialized(true) { new (&storage) T(value); } ~optional() : noexcept(NothrowDestructible<T>) { if (initialized) get().~T(); } }; 

optional ' . optional , optional , , optional . , copy move .


. : assignment . , . . copy constructor. :


 template<typename T> class optional { bool initialized; aligned_storage_t<sizeof(T), alignof(T)> storage; ... optional(optional const & other) noexcept(NothrowCopyConstructible<T>) : initialized(other.initialized) { if (initialized) new (&storage) T(other.get()); } optional& operator =(optional && other) noexcept(...) {...} }; 

move assignment. , :


  • optional ' , .
  • , .
  • , тАФ , , .

T : move constructor, move assignment :


 optional& operator =(optional && other) noexcept(...) { if (initialized) { if (other.initialized) { get() = move(other.get()); } else { initialized = false; other.initilized = true; new(&other.storage) T(move(get())); get().~T(); } } else if (other.initialized) { initialized = true; other.initialized = false; new(&storage) T(move(get())); other.get().~T(); } return *this; } 

noexcept :


 optional& operator =(optional && other) noexcept(NothrowAssignable<T> && NothrowMoveConstructible<T> && NothrowDestructible<T>) { if (initialized) { if (other.initialized) { get() = move(other.get()); } else { initialized = false; other.initialized = true; new (&other.storage) T(move(get())); get().~T(); } } ... } 

optional :


 template<typename T> class optional { ... optional(optional const &) noexcept(NothrowCopyConstructible<T>); optional(optional &&) noexcept(NothrowMoveConstructible<T>); optional& operator =(optional const &) noexcept(...); optional& operator =(optional &&) noexcept(...); }; 

, pair :
Optional -, (, deleted), compilation error.


 template class optional<unique_ptr<int>>; // compilation error 

, optional unique_ptr ,
copy constructor copy assignment deleted. , , SFINAE.
copy move assignment , тАФ . - , copy , .


тАФ . copy : deleted operation , , operation:


  • deleted_copy_construct delete , тАФ default ;
  • copy_construct , copy_construct .

 template<class Base> struct deleted_copy_construct : Base { deleted_copy_construct(deleted_copy_construct const &) = delete; deleted_copy_construct(deleted_copy_construct &&) = default; deleted_copy_construct& operator =(deleted_copy_construct const &) = default; deleted_copy_construct& operator =(deleted_copy_construct &&) = default; }; template<class Base> struct copy_construct : Base { copy_construct(copy_construct const & other) noexcept(noexcept(Base::construct(other))) { Base::construct(other); } copy_construct(copy_construct &&) = default; copy_construct& operator =(copy_construct const &) = default; copy_construct& operator =(copy_construct &&) = default; }; 

select_copy_construct , , CopyConstrictuble , copy_construct , deleted_copy_construct :


 template<typename T, class Base> using select_copy_construct = conditional_t<CopyConstructible<T> copy_construct<Base> deleted_copy_construct<Base> >; 

, optional , optional_base , copy construct , optional
select_copy_construct<T, optional_base<T>> . copy :


 template<typename T> class optional_base { ... void construct(optional_base const & other) noexcept(NothrowCopyConstructible<T>) { if ((initialized = other.initialized)) new (&storage) t(other.get()); } }; template<typename T> class optional : select_copy_construct<T, optional_base<T>> { ... }; 

. , , copy_construct , move_construct copy_construct , copy_assign , , move_construct , , , :


 template<typename T, class Base> using select_move_construct = select_copy_construct<T, conditional_t<MoveConstructible<T>, move_construct<Base> > >; template<typename T, class Base> using select_copy_assign = select_move_construct<T, conditional_t<CopyAssignable<T> && CopyConstructible<T>, copy_assign<Base> delete_copy_assign<Base> > >; 

, move_assign copy_assign , optional_base , assignment construct assign , optional select_move_assign<T, optional_base<T>> .


 template<typename T, class Base> using select_move_assign = select_copy_assign<T, ...>; template<typename T> class optional_base { ... void construct(optional_base const&) noexcept(NothrowCopyConstructible<T>); void construct(optional_base &&) noexcept(NothrowMoveConstructible<T>); optional_base& assign(optional_base &&) noexcept(...); optional_base& assign(optional_base const &) noexcept(...); }; template<typename T> class optional : select_move_assign<T, optional_base<T>> { ... }; 

, :
optional<unique_ptr> deleted_copy_construct ,
move_construct . !


 optional<unique_ptr<int>> : deleted_copy_construct<...> : move_construct<...> : deleted_copy_assign<...> : move_assign<...> : optional_base<unique_ptr<int>> 

: optional TriviallyCopyable TriviallyCopyable .


TriviallyCopyable ? , T TriviallyCopyable ,
memcpy . , .


, , , . resize vector TriviallyCopyable , memcpy , , . , , .


TriviallyCopyable , , static_assert ', copy-move :


 template<typename T> class optional : select_move_assign<T, optional_base<T>> {...}; static_assert(TriviallyCopyable<optional<int>>); static_assert(TriviallyCopyConstructible<optional<int>>); static_assert(TriviallyMoveConstructible<optional<int>>); static_assert(TriviallyCopyAssignable <optional<int>>); static_assert(TriviallyMoveAssignable <optional<int>>); static_assert(TriviallyDestructible <optional<int>>); 

static_assert ' . , , . optional тАФ aligned_storage , , , , TriviallyCopyable .


, . , TriviallyCopyable .


, . select_copy_construct :


 template<typename T, class Base> using select_copy_construct = conditional_t<CopyConstructible<T>, copy_construct<Base> deleted_copy_construct<Base> >; 

CopyContructible copy_construct , if compile-time: CopyContructible TriviallyCopyContructible , Base .


 template<typename T, class Base> using select_copy_construct = conditional_t<CopyConstructible<T>, conditional_t<TriviallyCopyConstructible<T>, Base, copy_construct<Base> >, deleted_copy_construct<Base> >; 

, copy . , select_destruct . int , - - , .


 template<typename T, class Base> using select_destruct = conditional_t<TriviallyDenstructible<T>, Base, destruct<Base> > >; 

, , . , , :


 optional<unique_ptr<int>> : deleted_copy_construct<...> : move_construct<...> : deleted_copy_assign<...> : move_assign<...> : destruct<optional_base<unique_ptr<int>>> : optional_base<unique_ptr<int>> 

, C++17 optional 7; : operation , deleted_operation select_operation ; construct assign . , .


- . . : deleted.


, noexcept .
, , , trivial , noexcept . , , trivial noexcept , noexcept , deleted . . , , .


type trait, , . , , copy : deleted , nothrow , ?


, - special member, , , , :


  • , deleted , = delete deleted_copy_construct ;
  • , copy_construct , c noexcept ;
  • , , , .

.


optional C++20


C++20 optional copy ?
:


  • T CopyConstructible , deleted ;
  • TriviallyCopyConstructible , ;
  • noexcept .

 template<typename T> class optional { ... optional(optional const &) requires(!CopyConstructible<T>) = delete; // #1 optional(optional const &) requires(TriviallyCopyConstructible<T>) = default; // #2 optional(optional const &) noexcept(NothrowCopyConstructible<T>) {...} // #3 ... ~optional() requires(TriviallyDestructible<T>) = default; ~optional() noexcept(NothroeDestructible<T>) {...} }; 

, . -, , T requires clause false . requires(false) , , overload resolution. , requires(true) , .
, .


requires clause = delete :


  • = delete overload resolution, , , deleted .
  • requires(false) overload resolution.

, copy , , requires clause. .


, . ! C++ , ? , , . , , , . , , , , , optional .


, , GCC internal compiler error, Clang . , . , .


, , optional C++20. , , C++17.


aligned_storage aligned_union


: aligned_storage reinterpret_cast , reinterpret_cast constexpr . , compile-time optional , compile-time. STL aligned_storage optional aligned_union variant . , , STL Boost optional variant . variant , :


 template<bool all_types_are_trivially_destructible, typename...> class _Variant_storage_; template<typename... _Types> using _Variant_storage = _Variant_storage_< conjunction_v<is_trivially_destructible<_Types>...>, _Types... >; template<typename _First, typename... _Rest> class _Variant_storage_<true, _First, _Rest...> { union { remove_const_t<First> _Head; _Variant_storage<_Rest...> _Tail; }; }; 

variant . _Variant_storage_ , , -, , variant , -, . , trivially_destructible ? type alias, . _Variant_storage_ , true false . , true , . trivially_destructible , union Variant ' .


, , , , . type alias _Variant_storage . :


 template<typename... _Types, bool = conjunction_v<is_trivially_destructible<_Types>...> > class _Variant_storage_; 

. , variadic template . , , , _Types . C++17 , .


C++20 ,
,
requires clause. C++20 requires clause:


 template<typename... _Types> class _Variant_storage_; template<typename _First, typename... _Rest> requires(TriviallyDestructible<_First> && ... && TriviallyDestuctible<_Rest>) class _Variant_storage_<_First, _Rest...> { union { remove_const_t<_First> _Head; _Variant_storage_<_Rest...> _Tail }; }; 

_Variant_storage_ , TriviallyDestructible . , requires clause , , .


requires clause template type alias


, requires clause template type alias. C++20 - enable_if , :


 template<bool condition, typename T = void> requires condition using enable_if_t = T; 

,


, . :


 // Equivalent, but functionally not equivalent template<typename T> enable_if_t<(sizeof(T) < 239)> f(); template<typename T> enable_if_t<(sizeof(T) > 239)> f(); // Not equivalent template<typename T> requires(sizeof(T) < 239) void f(); template<typename T> requires(sizeof(T) > 239) void f(); 

, enable_if . ? f() : enable_if , , 239, , , , 239. , :


  • , , template type alias', ┬лvoid f(); void f();
  • , SFINAE, , , .

, enable_if , , size < 239 , size > 239 . , . , f() . requires clause. тАФ , .


тАФ , . C++ Russia 2019 Piter, ┬л: core language┬╗ . , , : reachable entity visible, ADL, entities internal linkage . , C++ Russia (JetBrains) ┬л ++20 тАФ ?┬╗

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


All Articles