рд╕рдмрд╕реЗ рд╕рд╣реА рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░рд┐рдВрдЯрдл

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

рдХрд╣рд╛рдиреА


2009 рддрдХ рд╡рд╛рдкрд╕, рдЖрдЧрд╛рдореА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдорд┐рдердХ рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рджрд┐рдЦрд╛рдИ рджрд┐рдП рдЬреЛ рдЖрдкрдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рд╕рдм рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдЕрд░реНрдерд╛рддреН рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд╛рд░реНрд╕ред (рд╡реИрд╕реЗ, рднреВрдЦ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж ikalnitsky - рдореИрдВ рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рджреЗрдЦреЗрдВред) рдпрд╣ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд╕рд╛рде рдЙрдирдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд╣рд╛рдБ рдирд╣реАрдВ рдерд╛ред рдХреЗрд╡рд▓ рдбрд┐рдЬрд┐рдЯрд▓ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрдЯрд░реНрди рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рдФрд░ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдХреЗрд╡рд▓ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдХрдерд╛рдирдХред рдПрдХ рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рдХрджрдо


рддрдм рдореИрдВ рдкрд░реЗрд╢рд╛рди рдерд╛ред рд▓реЗрдХрд┐рди Google, рдореБрдЭреЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╕рдВрдХрд▓рди рдХреЗ рд╕рдордп рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред

рддреЛ, рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░рд┐рдВрдЯрдл рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред
template< class > struct FormatSupportedType; #define SUPPORTED_TYPE(C, T) \ template<> struct FormatSupportedType< T > { \ constexpr static bool supports(char c) { return c == C; } } SUPPORTED_TYPE('c', char); SUPPORTED_TYPE('d', int); template< std::size_t N > constexpr bool checkFormatHelper(const char (&format)[N], std::size_t current) { return current >= N ? true : format[current] != '%' ? checkFormatHelper( format, current + 1 ) : format[current + 1] == '%' ? checkFormatHelper( format, current + 2 ) : false; } template< std::size_t N, class T, class... Ts > constexpr bool checkFormatHelper(const char (&format)[N], std::size_t current, const T& arg, const Ts & ... args) { return current >= N ? false : format[current] != '%' ? checkFormatHelper( format, current + 1, arg, args... ) : (format[current] == '%' && format[current + 1] == '%') ? checkFormatHelper( format, current + 2, arg, args... ) : FormatSupportedType< T >::supports(format[current + 1]) && checkFormatHelper( format, current + 2, args... ); } template< std::size_t N, class... Ts > constexpr bool checkFormat(const char (&format)[N], const Ts & ... args) { return checkFormatHelper( format, 0, args... ); } int main() { static_assert( checkFormat("%c %d\n", 'v', 1), "Format is incorrect" ); } 

рдХрд╛рдо рдХрд╛ рддрд░реНрдХ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд╣реИ: рд╣рдо рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЙрд░реНрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░, рдкреНрд░рдХрд╛рд░ рдФрд░ рд╡рд░реНрдгреЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдз рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдорд░реНрдерди рдореМрдЬреВрдж рд╣реИ рдФрд░ рдкреНрд░рддреАрдХ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рдирддреАрдЬрддрди, рд╣рдо рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдкреНрд░рд╛рд░реВрдк рдХреА рд╢реБрджреНрдзрддрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдпрджрд┐ рдпрд╣ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдЕрдЧрд▓рд╛, рдХреНрд▓рд╛рд╕рд┐рдХ рдкреНрд░рд┐рдВрдЯрдл рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ , рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдВред
 template< std::size_t N, class... ARGS > int safe_printf(const char (&format)[N], ARGS... args) { static_assert( checkFormat(format, args... ), "Format is incorrect" ); return printf( format, args... ); } 

рд▓реЗрдХрд┐рди рдореЗрд░реА gcc-4.7 рдЗрд╕реЗ рдирд╣реАрдВ рдЦрд╛рдирд╛ рдЪрд╛рд╣рддреА рд╣реИ! рдореИрдВрдиреЗ рдЕрдЪрд╛рдирдХ рдлрд┐рд░ рд╕реЗ рдкрд░реЗрд╢рд╛рди рд╣реЛрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдВрддрд░реНрджреГрд╖реНрдЯрд┐ рдЖрдИред рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рд╡рд┐рд╡рд╢рддрд╛ рдХреЛ рд╕рдордЭрдирд╛ рд╣реЛрдЧрд╛ ред рдиреАрдЪреЗ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдЦ рдХрд╛ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕рд╛ред

рдкрд░рд┐рдгрддрд┐ред рдЕрдбрд╝рдЪрди рд╕рдордЭрдирд╛


рдкрд╣рд▓реЗ рдХреНрдпрд╛ рд╣реБрдЖ рдерд╛? рдПрдХ рд╕рдВрдХрд▓рди рдЪрд░рдг рдФрд░ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдЪрд░рдг рд╣реБрдЖ рдХрд░рддрд╛ рдерд╛, рдпрд╣ рднреА рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╣рд░ рдХреЛрдИ рдпрд╣ рдЬрд╛рдирддрд╛ рд╣реИ) рдХрд┐ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдЯрд╛рдЗрдкрд┐рдВрдЧ рд╣реЛрддреА рд╣реИред
рдЕрдм рдХреНрдпрд╛ рд╣реИ? рдЕрдм рдмрд╛рдзрд╛ рд╣реИ , рдЬреЛ рдЖрдкрдХреЛ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ - рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рджрдВрдб рд╕рд╛рдордиреЗ рдЖрддрд╛ рд╣реИред рд╣рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ рдкреЗрд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рд╣рдо рди рдХреЗрд╡рд▓ рд╕рдВрдХрд▓рди рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдмрд▓реНрдХрд┐ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рднрд╛рдЧреЛрдВ рдХреЗ рд╕рдВрдХрд▓рди рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХрд╛рд░реНрдп, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ) рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "рдлрд╝рдВрдХреНрд╢рди f рдХрд╛ рд╕рдВрдХрд▓рди", "рдлрд╝рдВрдХреНрд╢рди f рдХрд╛ рд░рдирдЯрд╛рдЗрдо", "рд╕рдВрдкреВрд░реНрдг рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рд╕рдВрдХрд▓рди", "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рд░рдирдЯрд╛рдЗрдо"ред
рдпрд╣реА рд╣реИ, рдЕрдм рдкреВрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рд╕рдВрдХрд▓рди рдЪрд░рдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд╡рд┐рднрд┐рдиреНрди рдЗрдХрд╛рдЗрдпреЛрдВ рдХреЗ рд╕рдВрдХрд▓рди рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдореЗрдВ рдЯреВрдЯ рдЧрдпрд╛ рд╣реИред рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВред
 template< int N > constexpr int f(int n) { return N + n; } int main() { constexpr int i0 = 1; constexpr int i1 = f<i0>(i0); constexpr int i2 = f<i1>(i1); static_assert(i2 == 4, ""); } 

рдореБрдЭреЗ рддреБрд░рдВрдд рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдпрд╣ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдХреБрдЫ рднреА рдЙрдкрдпреЛрдЧреА рдирд╣реАрдВ рд╣реИ ред рдЖрдЗрдП рдореБрдЦреНрдп () рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдВрдХрд▓рди рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╡реИрд░рд┐рдПрдмрд▓ I0 рдХреЛ рдПрдХ рдорд╛рди рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рдЗрд╕ рд╡реИрд░рд┐рдПрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡реИрд░рд┐рдПрдмрд▓ I1 рдХреЗ рдорд╛рди рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди f <i0> (i0) рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рд╕рдВрдХрд▓рди рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдорд╛рди i0 рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕реА рддрд░рд╣ f <i1> (i1) рдХреЗ рд╕рд╛рде ред рдпрд╣реА рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ: рдореБрдЦреНрдп () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди f <1> (int) рдХрд╛ рдЕрдиреБрдХреНрд░рдорд┐рдХ рд╕рдВрдХрд▓рди рд╣реИ, рдлрд┐рд░ рдЗрд╕рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди, рдлрд┐рд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╕рдВрдХрд▓рди f <2> (int) , рдФрд░, рддрджрдиреБрд╕рд╛рд░, рдЗрд╕рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрдиред
рдпрд╣ рдХреНрдпрд╛ рд╣реИ? рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕реЗ рдХреЙрдиреНрд╕реНрдЯреИрдХреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╡рд╣ рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреА рддрд░рд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЖрдЗрдП рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреЗрдЦреЗрдВ f : N рдХреЛ рдЗрд╕рдХреЗ рд╕рдВрдХрд▓рди рдХреЗ рдЪрд░рдг рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ n - рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдЪрд░рдг рдореЗрдВред

рдЕрд▓рдЧрд╛рд╡ред рд╕реБрд░рдХреНрд╖рд┐рдд Printf рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛


рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛!
 template< class... ARGS > int safe_printf(const char* format, ARGS... args) { static_assert( checkFormat(format, args... ), "Format is incorrect"); return printf( format, args... ); } 

static_assert рдХреЛ safe_printf рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдЕрдиреБрдорддрд┐ рджреА рдЧрдИ рд╣реИ, рдФрд░ рдкреНрд░рд╛рд░реВрдк рдХреЗрд╡рд▓ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рдордп рд╣реА рдЬрд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ (рднрд▓реЗ рд╣реА рд╕рдВрдХрд▓рди рдЪрд░рдг рдЗрд╕ рд╕рдордп рдХреБрдЫ рдФрд░ рдХреЗ рд▓рд┐рдП рд╣реЛ)ред
рдФрд░ рдЖрдк рдЗрд╕рдХреЗ рдЖрд╕-рдкрд╛рд╕ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪреЗ? рд▓реЗрдХрд┐рди рдХреЛрдИ рднреА рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ, рдпрд╛ рдкреНрд░рд╛рд░реВрдк рд╡рд░реНрдгреЛрдВ рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдореЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╡реЗ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗ (рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ, рдХрд╕реНрдЯрдо рд╢рд╛рдмреНрджрд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ) рдпрд╛ рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдЬрдм рд╕рдм рдХреБрдЫ рд╕реБрдкрд░ рдХреВрд▓, рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдФрд░ рдЕрдЬреЗрдп C + рд╣реИред + (рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕реА ++ 11) рдЕрд╕рд╣рд╛рдп рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рдореИрдХреНрд░реЛрдЬрд╝ рджреГрд╢реНрдп рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реИрдВ!
 #define safe_printf(FORMAT, ...) \ static_assert(checkFormat( FORMAT, __VA_ARGS__ ), "Format is incorrect"); \ printf(FORMAT, __VA_ARGS__) int main() { safe_printf("%c %d\n", 'v', 1); } 

рдЬреАрдд!

Denouement - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рд╣реБрдЖ рдпрд╛ рдЧреИрд░-рдзреБрд▓рдиреЗ рд╡рд╛рд▓рд╛ рдХрд┐рдирд╛рд░рд╛


рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рдкрд╣рд▓реЗ рд╣рдо рдПрдХ рд╕реБрдЦрдж рдЕрдВрдд рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдпрд╣ рдХреИрд╕реЗ рдирд┐рдХрд▓рд╛ред рдиреАрдЪреЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░рд┐рдВрдЯ рдХрд╛ рд╕рд╣реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред
 template< char... > struct TemplateLiteral { }; template< char... FORMAT, class... ARGS > int safe_printf_2(TemplateLiteral<FORMAT...>, ARGS... args) { constexpr char format[] = {FORMAT... , '\0'}; static_assert( checkFormat(format, args... ), "Format is incorrect"); return printf( format, args... ); } int main() { safe_printf_2(_("%c %d\n"), 'v', 2); } 

рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдПрдХ рдЪрд░ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рдирдХреА TYPE рд╣рдорд╛рд░реЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ (рдФрд░ рдореВрд▓реНрдп рдирд╣реАрдВ), рдФрд░ рдЙрди рддрд░реНрдХреЛрдВ рдХреЛ рдЬрд┐рдиреНрд╣реЗрдВ рдХрдЯреМрддреА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдПрдХ рд╢рд╛рдмреНрджрд┐рдХ рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИред рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдпрд╣ рд╢рд╛рдВрдд рд╣реЛрдЧрд╛ рдпрджрд┐, рдЬрд┐рд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╢рд╛рдмреНрджрд┐рдХ рдореМрдЬреВрдж рд╣реИ, рд╡рд╣рд╛рдБ рдЕрднреА рднреА рдЗрд╕ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХрд╛ рдПрдХ рдкреИрдХреЗрдЯ рд╣реЛрдЧрд╛ (рдХреБрдЫ рдЕрд▓рдЧ рдХрд░рдирд╛), рддрд╛рдХрд┐ рдпрд╣ рддрдм рдЕрдирдкреИрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдЕрд░реНрдерд╛рддреНред
 template< std::size_t... INDXs > //... TemplateLiteral<"some literal"[INDXs]...> //... 

рд▓реЗрдХрд┐рди рд╢рд╛рдмреНрджрд┐рдХ рдХреА рд▓рдВрдмрд╛рдИ рдФрд░ рдкреИрдХ рдХреА рд▓рдВрдмрд╛рдИ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЪреВрдВрдХрд┐ рдкреИрдХ рдХреЗрд╡рд▓ рдмрд╛рд╣рд░ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рд╢рд╛рдмреНрджрд┐рдХ рдХреЛ рдмрд╛рд╣рд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдпрджрд┐ рдЗрд╕реЗ рдмрд╛рд╣рд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рд▓реЗрдХрд┐рди рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдбрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рдХреЛрдИ рддрдВрддреНрд░ рдирд╣реАрдВ рд╣реИ), рддреЛ рдЗрд╕реЗ рд╕рд░рд▓ рд░реВрдк рдореЗрдВ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рддрд░реНрдХ, рдФрд░ рдЗрд╕рд▓рд┐рдП рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рдЪрд░рдг рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЗрд╕реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ, рдФрд░ рдкреНрд░рдХрд╛рд░ рд╕рдВрдХрд▓рди рд╣реИрдВ - рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдпрд╣ рдЕрд╕рдВрднрд╡ рд╣реИред
рд▓реЗрдХрд┐рди рдореИрдХреНрд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдпрд╛рдж рдХрд░реЗрдВред рдЖрдк рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдврд╝рд╛рд╡рд╛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП :: рдкреВрд░реНрд╡рдкреНрд░рдХреНрд░рдордХ рдкреВрдЫ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ, рдЙрдирдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реНрдерд┐рд░ рд╣реЛрдЧреА, рдФрд░ рдЗрд╕реЗ рдХреЗрд╡рд▓ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рдЪрд░рдг рдореЗрдВ рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдпрд╣ рднреА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рд╕рдВрдХрд▓рди рдЪрд░рдг рдкрд░ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рд╕реВрдЪрдХрд╛рдВрдХ рд╕реЗ рддрддреНрд╡ рд▓реЗрдирд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕реБрд░рдХреНрд╖рд╛рддреНрдордХ рддрдВрддреНрд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкрдВрдХреНрддрд┐ рдХреЗ рдЕрдВрдд рдХреЛ рд╕рд╛рдл рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ред рдФрд░ рдЖрдкрдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рднреА рдЬрд╝рд░реВрд░рдд рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕рднреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреИрдкреНрдЪрд░ рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдЕрд░реНрдерд╛рддреНред рдХреНрдпрд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдиреЗ рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рд╡реЗрд╢ рдХрд┐рдпрд╛? рдиреАрдЪреЗ рдХреЛрдб рд╣реИред
 template< char... > struct TemplateLiteral { }; //       ; //      ,    template< std::size_t LEN, char CHAR, char... CHARS > struct TemplateLiteralTrim { private: //      //   - ,       template< bool, class, char... > struct Helper; template< char... C1, char... C2 > struct Helper< false, TemplateLiteral<C1...>, C2... > { //  , static_assert(sizeof...(C1) == LEN, "Literal is too large"); typedef TemplateLiteral<C1...> Result; }; template< char... C1, char c1, char c2, char... C2 > struct Helper< true, TemplateLiteral<C1...>, c1, c2, C2... > { typedef typename Helper< (bool)c2, TemplateLiteral<C1..., c1>, c2, C2...>::Result Result; }; public: typedef typename Helper<(bool)CHAR, TemplateLiteral<>, CHAR, CHARS..., '\0' >::Result Result; }; template< class T, std::size_t N > constexpr inline std::size_t sizeof_literal( const T (&)[N] ) { return N; } //      N-   template< std::size_t M > constexpr inline char getNthCharSpec( std::size_t N, const char (&literal)[M] ) { return N < M ? literal[N] : '\0'; } #define GET_Nth_CHAR_FOR_PP(I, N, LIT) ,getNthCharSpec(N, LIT) //      //      , // -      , //    #define TEMPLATE_LITERAL_BASE(MAX, LIT) \ (typename TemplateLiteralTrim< sizeof_literal(LIT) - 1 \ BOOST_PP_REPEAT(MAX, GET_Nth_CHAR_FOR_PP, LIT) >::Result()) // MAX_SYM         #define TEMPLATE_LITERAL(LITERAL) TEMPLATE_LITERAL_BASE(MAX_SYM, LITERAL) int main() { //  safe_printf_2(TEMPLATE_LITERAL("%c %d\n"), 'v', 2); } 

рд╡реИрд╕реЗ, рдореБрдЭреЗ рдмрдврд╝рд╛рд╡рд╛ рджреЗрдиреЗ рдореЗрдВ рджреЗрдЦрдирд╛ рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдк рдерд╛ :: рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ - рдореИрдВрдиреЗ рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рдХреА рдХрд┐ рд╡реЗ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЬреИрд╕реЗ рдЕрдВрдХрдЧрдгрд┐рддреАрдп рд╕рдВрдЪрд╛рд▓рди)ред рддреЛ рдореИрдХреНрд░реЛрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рднрдпрд╛рдирдХ рд╢рдХреНрддрд┐ рд╣реИрдВред

рдЕрд╕рдВрдмрдВрдзрд┐рдд рдлреНрд░реЗрдоред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХрд╛ рдкреБрдирд░реНрд╡рд╛рд╕


рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдХреНрдпреЛрдВ рдЙрдиреНрд╣реЗрдВ (рд╢рд╛рдмреНрджрд┐рдХ) рд╕рдореНрдорд╛рди рджреЗрдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред рдПрдХ рдмрд╛рд░, рд▓рдЧрднрдЧ рджреЛ рд╕рд╛рд▓ рдкрд╣рд▓реЗ, рдореБрдЭреЗ рдЯреНрдпреВрдкрд▓реНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдЪрд▓рд╛ред рд╡реЗ рдореЗрд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд▓рдЧ рд░рд╣реЗ рдереЗ, рд▓реЗрдХрд┐рди рдЗрди рдЯреБрдкрд▓реНрд╕ рдкрд╛рдпрдерди, рдиреЗрдорд░реНрд▓ рдФрд░ рд╣рд╛рд╕реНрдХреЗрд▓ рд╕реЗ рдереЗред рдФрд░ рдЬрдм рдореИрдВрдиреЗ C ++ рд╕реЗ рдЯреНрдпреВрдкрд▓реНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реАрдЦрд╛, рддреЛ рдореИрдВ std :: get <N> (tuple) рд╕реЗ рдмрд╣реБрдд рдкрд░реЗрд╢рд╛рди рдерд╛ - рдпрд╣ рдмреЛрдЭрд┐рд▓ рд╣реИ, рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдерд╛, рдФрд░ рддрдм рд╕реЗ рдореИрдВ рдПрдХ рддрддреНрд╡ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╡рд░реНрдЧ рдмреНрд░реИрдХреЗрдЯ рдСрдкрд░реЗрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗред рдФрд░ рдпрд╣рд╛рдБ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдмрдЪрд╛рд╡ рдореЗрдВ рдЖрдПред
 template< std::size_t > struct Number2Type { }; template< class... Ts > class tupless: public std::tuple<Ts...> { public: template< class... ARGS > tupless(ARGS... args): std::tuple<Ts...>(args...) { } template< std::size_t N > auto operator[](Number2Type<N>) const -> decltype(std::get<N>(std::tuple<Ts...>())) const& { return std::get<N>(*this); } template< std::size_t N > auto operator[](Number2Type<N>) -> decltype(std::get<N>(std::tuple<Ts...>())) & { return std::get<N>(*this); } }; template< std::size_t N > constexpr std::size_t chars_to_int(const char (&array)[N], std::size_t current = 0, std::size_t acc = 0) { return (current >= N || array[current] == 0) ? acc : chars_to_int(array, current + 1, 10 * acc + array[current] - '0'); }; template<char... Cs> constexpr auto operator "" _t() -> Number2Type<chars_to_int((const char[1 + sizeof...(Cs)]){Cs..., '\0'})> { return {}; //      }; int main() { tupless<char, int, float> t('x', 10, 12.45); safe_printf_2(TEMPLATE_LITERAL("%c %d %f"), t[0_t], t[1_t], t[2_t]); } 

рдХреНрдпрд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ? рдареАрдХ рд╣реИ, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рджреЛ рдмрд╛рд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдЬреЛ рдПрдХ рд╢рд╛рдмреНрджрд┐рдХ рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ (рдЕрд░реНрдерд╛рдд, рдкреНрд░рдХрд╛рд░ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ), рдПрдХ рдЦрд╛рд▓реА рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдЗрд╕реЗ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдбрд╛рд▓рдиреЗ рдФрд░ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЛ рд╡рд╣рд╛рдВ рдбрд╛рд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдЧрд╛ред
рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдЗрд╕рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╕реАрдзреЗ рдореВрд▓реНрдп рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреНред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ 2_t рдирдВрдмрд░ 2 рдЯрд╛рдЗрдк <2> рд╣реЛрдЧрд╛ ред рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд╕рднреА рд▓реЛрдЧ рд╕рд╣рдЬ рд╣реЛрдВрдЧреЗред
рдмреЗрд╢рдХ, рдЗрд╕реЗ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ ...

рдЕрджреНрдпрддрди: рдореИрдХреНрд░реЛ рдХреЗ рдмрдЬрд╛рдп рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ

рдЕрджреНрдпрддрди: рд╡рд┐рд╖рдп рдХреЛ "рдЕрд╕рд╛рдорд╛рдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ" рдкрд░ рд▓реЗ рдЬрд╛рдпрд╛ рдЧрдпрд╛, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЙрд╕рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ рдЕрдзрд┐рдХ рдЖрд░рд╛рдорджрд╛рдпрдХ рд╣реЛрдЧрд╛ред

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


All Articles