рдлрд┐рд░ рд╕реЗ рдирдорд╕реНрдХрд╛рд░ред рд╣рдо рдЖрдкрдХреЗ рд╕рд╛рде рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рд▓реЗрдЦ рд╕рд╛рдЭрд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдПрдХ рдЕрдиреБрд╡рд╛рдж рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкрд╛рдареНрдпрдХреНрд░рдо "C ++ рдбреЗрд╡рд▓рдкрд░" рдХреЗ рдЫрд╛рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЖрдЬ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Bal├бzs рджреНрд╡рд╛рд░рд╛ рдПрдХ рдЕрддрд┐рдерд┐ рдкреЛрд╕реНрдЯ рд╣реИред рдПрдбрдо Verizon рд╕реНрдорд╛рд░реНрдЯ рдХрдореНрдпреБрдирд┐рдЯреАрдЬрд╝ рд╣рдВрдЧрд░реА рдореЗрдВ рдПрдХ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдЗрдВрдЬреАрдирд┐рдпрд░ рд╣реИ рдФрд░ рдПрдореНрдмреЗрдбреЗрдб рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рд╡реАрдбрд┐рдпреЛ рдПрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЙрдирдХрд╛ рдПрдХ рдЬреБрдиреВрди рд╕рдВрдХрд▓рди рд╕рдордп рдХрд╛ рдЕрдиреБрдХреВрд▓рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡рд╣ рддреБрд░рдВрдд рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдПрдХ рдЕрддрд┐рдерд┐ рдкреЛрд╕реНрдЯ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣рдордд рд╣реБрдПред рдЖрдк рдПрдбрдо рдХреЛ
рд▓рд┐рдВрдХреНрдбрдЗрди рдкрд░ рдСрдирд▓рд╛рдЗрди рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
SFINAE рдХреЛ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ
рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ , рд╣рдордиреЗ рджреЗрдЦрд╛ рдХрд┐ рдХреИрд╕реЗ рд╣рдорд╛рд░реЗ SFINAE рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдмрд╣реБрдд
рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рдЕрднрд┐рд╡реНрдпрдВрдЬрдХ рдмрдирд╛рдпрд╛ рдЬрд╛рдП ред
рдмрд╕ рдЗрд╕рдХреЗ рдореВрд▓ рд░реВрдк рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
template<typename T> class MyClass { public: void MyClass(T const& x){} template<typename T_ = T> void f(T&& x, typename std::enable_if<!std::is_reference<T_>::value, std::nullptr_t>::type = nullptr){} };
рдФрд░ рдЗрд╕реЗ рдЗрд╕ рдЕрдзрд┐рдХ рдЕрднрд┐рд╡реНрдпрдВрдЬрдХ рд░реВрдк рд╕реЗ рддреБрд▓рдирд╛ рдХрд░реЗрдВ:
template<typename T> using IsNotReference = std::enable_if_t<!std::is_reference_v<T>>; template<typename T> class MyClass { public: void f(T const& x){} template<typename T_ = T, typename = IsNotReference <T_>> void f(T&& x){} };
рд╣рдо рдпрдереЛрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдФрд░ рдЖрд░рд╛рдо рдХрд░рдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдВрднрд╡ рд╣реИред рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди - рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВ - рд╣рдорд╛рд░рд╛ рдХреЛрдб рд╕реБрд░рдХреНрд╖рд┐рдд рдФрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреНрдпрд╛ рдРрд╕рд╛ рд╣реИ? рдЪрд▓реЛ рдЗрд╕реЗ рд╣реИрдХ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ!
рджреЛрд╖ # 1: SFINAE рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
рдЖрдорддреМрд░ рдкрд░, рд╕реНрдерд┐рддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЛрдб рдХреЗ рднрд╛рдЧ рдХреЛ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП SFINAE рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЕрдЧрд░ рд╣рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд┐рд╕реА рдХрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдкрд░рд┐рднрд╛рд╖рд┐рдд рдПрдмреНрд╕ рдлрд╝рдВрдХреНрд╢рди (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЕрдВрдХрдЧрдгрд┐рддреАрдп рд╡рд░реНрдЧ, рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рди, рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрджрд┐):
template< typename T > T myAbs( T val ) { return( ( val <= -1 ) ? -val : val ); } int main() { int a{ std::numeric_limits< int >::max() }; std::cout << "a: " << a << " myAbs( a ): " << myAbs( a ) << std::endl; }
рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрд╛рдлреА рд╕рд╛рдорд╛рдиреНрдп рджрд┐рдЦрддрд╛ рд╣реИ:
a: 2147483647 myAbs( a ): 2147483647
рд▓реЗрдХрд┐рди рд╣рдо рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ
abs
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдкреНрд░рднрд╛рд╡ рд╡рд┐рдирд╛рд╢рдХрд╛рд░реА рд╣реЛрдЧрд╛:
nt main() { unsigned int a{ std::numeric_limits< unsigned int >::max() }; std::cout << "a: " << a << " myAbs( a ): " << myAbs( a ) << std::endl; }
рджрд░рдЕрд╕рд▓, рдЕрдм рдХрд╛рд░реНрдпрдХреНрд░рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ:
a: 4294967295 myAbs( a ): 1
рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ SFINAE рдХреЗ рд╕рд╛рде
T
рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рд╕реЗрдЯ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
template< typename T > using IsSigned = std::enable_if_t< std::is_signed_v< T > >; template< typename T, typename = IsSigned< T > > T myAbs( T val ) { return( ( val <= -1 ) ? -val : val ); }
рдХреЛрдб рдЕрдкреЗрдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: рдПрдХ рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде myAbs рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рд╕рдВрдХрд▓рди-рд╕рдордп рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ:
candidate template ignored: requirement 'std::is_signed_v<
unsigned int>' was not satisfied [with T = unsigned int]
рд╣реИрдХрд┐рдВрдЧ SFINAE рд░рд╛рдЬреНрдп
рдлрд┐рд░ рдЗрд╕ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ рдХреНрдпрд╛ рдЧрд▓рдд рд╣реИ? рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ myAbs SFINAE рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред
template< typename T, typename = IsSigned<T> > T myAbs( T val );
myAbs
рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЗрдирдкреБрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИрдВред рдкрд╣рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдХрд╛рд░ рд╣реИ, рджреВрд╕рд░рд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ
IsSigned <
T >
(рдЕрдиреНрдпрдерд╛
std::enable_if_t <
std::is_signed_v <
T >
>
рд╡рд░рдирд╛
std::enable_if <
std::is_signed_v <
T>, void>::type
, рдЬреЛ
void
рдпрд╛ рд╡рд┐рдлрд▓ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╣реИ)ред
рд╣рдо
myAbs
рдХреИрд╕реЗ рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ? 3 рддрд░реАрдХреЗ рд╣реИрдВ:
int a{ myAbs( -5 ) }; int b{ myAbs< int >( -5 ) }; int c{ myAbs< int, void >( -5 ) };
рдкрд╣рд▓реА рдФрд░ рджреВрд╕рд░реА рдХреЙрд▓ рд╕реАрдзреА рд╣реИ, рд▓реЗрдХрд┐рди рддреАрд╕рд░реА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ:
void
рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рддрд░реНрдХ рдХреНрдпрд╛ рд╣реИ?
рджреВрд╕рд░рд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдирд╛рдо рд╣реИ, рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рдХрд╛рд░ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рднреА рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдк рдЗрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ? рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдмрдбрд╝реА рд╕рдорд╕реНрдпрд╛ рд╣реИред рд╣рдо рдЕрдкрдиреЗ SFINAE рдЪреЗрдХ рдХреЛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреАрд╕рд░реЗ рдлреЙрд░реНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
unsigned int d{ myAbs< unsigned int, void >( 5u ) }; unsigned int e{ myAbs< unsigned int, void >( std::numeric_limits< unsigned int >::max() ) };
рдпрд╣ рдХреЛрдб рдареАрдХ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд┐рдирд╛рд╢рдХрд╛рд░реА рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдордиреЗ SFINAE рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛:
a: 4294967295 myAbs( a ): 1
рд╣рдо рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░реЗрдВрдЧреЗ - рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ: рдХреНрдпрд╛ рдХреЛрдИ рдЕрдиреНрдп рдиреБрдХрд╕рд╛рди рд╣реИрдВ? рдЦреИрд░ ...
рджреЛрд╖ # 2: рд╣рдо рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ
SFINAE рдХрд╛ рдПрдХ рдЕрдиреНрдп рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрдпреЛрдЧ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдВрдХрд▓рди-рд╕рдордп рдХреА рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╣реИред рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо
myAbs
рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде
myAbs
рдХреА рдХреЙрд▓ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдФрд░ рдЗрди рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рддреБрдЪреНрдЫ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ? рд╣рдо C ++ 17 рдореЗрдВ рдХреЙрдиреНрд╕реНрдЯреИрдХреНрд╕рдкреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рдо рдмрд╛рдж рдореЗрдВ рдЗрд╕ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВрдЧреЗ), рдпрд╛ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
template< typename T > using IsSigned = std::enable_if_t< std::is_signed_v< T > >; template< typename T > using IsUnsigned = std::enable_if_t< std::is_unsigned_v< T > >; template< typename T, typename = IsSigned< T > > T myAbs( T val ) { return( ( val <= -1 ) ? -val : val ); } template< typename T, typename = IsUnsigned< T > > T myAbs( T val ) { return val; }
рд▓реЗрдХрд┐рди рдпрд╣ рдХреНрдпрд╛ рд╣реИ?
error: template parameter redefines default argument template< typename T, typename = IsUnsigned< T > > note: previous default template argument defined here template< typename T, typename = IsSigned< T > >
рдУрд╣, C ++ рдорд╛рдирдХ (C ++ 17; .117.1.16) рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдмрддрд╛рддрд╛ рд╣реИ :"рдПрдХ рд╣реА рджрд╛рдпрд░реЗ рдореЗрдВ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдШреЛрд╖рдгрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реНрдХ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред"
рдУрд╣, рдпрд╣ рдареАрдХ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛ ...
рдЕрдЧрд░ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░рддреЗ?
рд╣рдо рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рд░рдирдЯрд╛рдЗрдо рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
template< typename T > T myAbs( T val ) { if( std::is_signed_v< T > ) { return ( ( val <= -1 ) ? -val : val ); } else { return val; } }
рд╕рдВрдХрд▓рдХ рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдХрд░реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐
if (std::is_signed_v <
T>)
рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж
if (true)
рдпрд╛
if (false)
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рдВ,
myAbs
рд╣рдорд╛рд░реЗ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ
myAbs
рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рд▓реЗрдХрд┐рди рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдпрд╣ рдПрдХ рдмрд╣реБрдд рдмрдбрд╝реА рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ:
if
рдФрд░
else
рдкреНрд░рддреНрдпреЗрдХ
T
рд▓рд┐рдП рдорд╛рдиреНрдп рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП
T
рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдереЛрдбрд╝рд╛ рдмрджрд▓рддреЗ рд╣реИрдВ:
template< typename T > T myAbs( T val ) { if( std::is_signed_v< T > ) { return std::abs( val ); } else { return val; } } int main() { unsigned int a{ myAbs( 5u ) }; }
рд╣рдорд╛рд░рд╛ рдХреЛрдб рддреБрд░рдВрдд рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛:
error: call of overloaded 'abs(unsigned int&)' is ambiguous
рдпрд╣ рдкреНрд░рддрд┐рдмрдВрдз рд╡рд╣ рд╣реИ рдЬреЛ SFINAE рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ: рд╣рдо рд╡рд╣ рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХреЗрд╡рд▓ T рдХреЗ рд╕рдмрд╕реЗрдЯ рдХреЗ рд▓рд┐рдП рдорд╛рдиреНрдп рд╣реИ (myAbs рдореЗрдВ рдпрд╣ рдХреЗрд╡рд▓ рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рдиреНрдп рд╣реИ рдпрд╛ рдХреЗрд╡рд▓ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рдиреНрдп рд╣реИ)ред
рд╕рдорд╛рдзрд╛рди: SFINAE рдХреЗ рд▓рд┐рдП рджреВрд╕рд░рд╛ рд░реВрдк
рдЗрди рдХрдорд┐рдпреЛрдВ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдкрд╣рд▓реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреЗ SFINAE рдЪреЗрдХ рдХреЛ рдмрд╛рдзреНрдп рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рднрд▓реЗ рд╣реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рджреВрд╕рд░реЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрджрд┐ рд╣рдо рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рдХрд╛рд░ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ SFINAE рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛? рдЖрдЗрдП рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ:
template< typename T > using IsSigned = std::enable_if_t< std::is_signed_v< T >, bool >; template< typename T, IsSigned< T > = true > T myAbs( T val ) { return( ( val <= -1 ) ? -val : val ); } int main() {
рд╣рдореЗрдВ рд╡реИрдз рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╢реВрдиреНрдп рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реЛрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╢реВрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдореВрд▓реНрдп рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреБрдЫ рдФрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП: рдмреВрд▓, рдЗрдВрдЯ, рдПрдирдо, рдирд▓реНрдЯрдкреНрд░__, рдЖрджрд┐ред рдЖрдорддреМрд░ рдкрд░ рдореИрдВ рдмреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ - рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рднрд╛рд╡ рд╕рд╛рд░реНрдердХ рджрд┐рдЦрддреЗ рд╣реИрдВ:
template< typename T, IsSigned< T > = true >
рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!
myAbs (5u)
рдХрдВрдкрд╛рдЗрд▓рд░ рдкрд╣рд▓реЗ рдХреА рддрд░рд╣ рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИ:
candidate template ignored: requirement 'std::is_signed_v<unsigned int>' was not satisfied [with T = unsigned int
рджреВрд╕рд░реА рдХреЙрд▓,
myAbs <
int> (5u)
рдЕрднреА рднреА рдорд╛рдиреНрдп рд╣реИ, рд╣рдо рд╕рдВрдХрд▓рдХ рдкреНрд░рдХрд╛рд░
T
рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдмрддрд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣
5u
рдХреЛ
int
рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдЕрдВрдд рдореЗрдВ, рд╣рдо рдЕрдм рдЙрдВрдЧрд▓реА рдХреЗ рдЖрд╕рдкрд╛рд╕
myAbs
рдкрддрд╛ рдирд╣реАрдВ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ:
myAbs <
unsigned int, true> (5u)
рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рд╣рдо рдХреЙрд▓ рдореЗрдВ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ, SFINAE рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рднрд╛рдЧ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рд╡реИрд╕реЗ рднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдХрд▓рдХ рдХреЛ рдПрдХ рдЕрдирд╛рдо рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рди рдХреЗ рддрд░реНрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рд╣рдо рдЕрдЧрд▓реА рд╕рдорд╕реНрдпрд╛ рдкрд░ рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ - рд▓реЗрдХрд┐рди рдПрдХ рдорд┐рдирдЯ рд░реБрдХрд┐рдП! рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдм рд╣рдо рд╕рдорд╛рди рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реНрдХ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдореВрд▓ рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рдереА?
template< typename T, typename = IsUnsigned< T > > T myAbs( T val ); template< typename T, typename = IsSigned< T > > T myAbs( T val );
рд▓реЗрдХрд┐рди рдЕрдм рд╡рд░реНрддрдорд╛рди рдХреЛрдб рдХреЗ рд╕рд╛рде:
template< typename T, IsUnsigned< T > = true > T myAbs( T val ); template< typename T, IsSigned< T > = true > T myAbs( T val );
рдпрд╣ рдкрд┐рдЫрд▓реЗ рдХреЛрдб рдХреЗ рд╕рдорд╛рди рджрд┐рдЦрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдпрд╛ рддреЛ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдХреЛрдб рдореЗрдВ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред
IsUnsigned <
T>
рдХреНрдпрд╛ рд╣реИ? рдмреВрд▓ рдпрд╛ рдЕрд╕рдлрд▓ рд▓реБрдХред рдФрд░
IsSigned <
T>
рдХреНрдпрд╛ рд╣реИ? рдПрдХ рд╣реА рдмрд╛рдд рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдмреВрд▓ рд╣реИ, рддреЛ рджреВрд╕рд░рд╛ рдПрдХ рдЕрд╕рдлрд▓ рд▓реБрдХрдЕрдк рд╣реИред
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реНрдХреЛрдВ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ рдмреВрд▓ рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рджреВрд╕рд░рд╛ рдПрдХ рдЕрд╕рдлрд▓ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред
рд╕рд┐рдВрдереЗрдЯрд┐рдХ рдЪреАрдиреА
рдпреБрдкреАрдбреАред рдЗрд╕ рдЕрдиреБрдЪреНрдЫреЗрдж рдХреЛ рд▓реЗрдЦрдХ рджреНрд╡рд╛рд░рд╛ рдЗрд╕рдореЗрдВ рдорд┐рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░рдг рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛редC ++ рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдг
рдЙрдкрд░реЛрдХреНрдд рд╕рднреА C ++ 11 рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ рдорд╛рдирдХ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рдмреАрдЪ рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреА рдХреНрд░рд┐рдпрд╛рд╢реАрд▓рддрд╛ рд╣реИ:
рд▓реЗрдХрд┐рди рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд╣реА рд░рд╣рддрд╛ рд╣реИ:
template< typename T, IsSigned< T > = true >
рдЕрдЪреНрдЫреЗ рдкреБрд░рд╛рдиреЗ C ++ 98 рдореЗрдВ, рдХреЛрдИ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЙрдкрдирд╛рдо рдирд╣реАрдВ рд╣реИрдВ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдлрд╝рдВрдХреНрд╢рди рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдпрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЕрдкрдиреЗ SFINAE рдХреЛрдб рдХреЛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк рдЕрдиреБрд╢рдВрд╕рд┐рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рдХрд╛рд░ рдирд╣реАрдВ рд╣реИрдВред рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣рдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
template< typename T > T myAbs( T val, typename my_enable_if< my_is_signed< T >::value, bool >::type = true ) { return( ( val <= -1 ) ? -val : val ); }
рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП рдмрд╕ - C ++ рдХрд╛ рдЖрдзреБрдирд┐рдХ рд╕рдВрд╕реНрдХрд░рдг:
template< typename T, IsSigned< T > = true > T myAbs( T val ) { return( ( val <= -1 ) ? -val : val ); }
рд╕реА ++ 98 рд╕рдВрд╕реНрдХрд░рдг рдмрджрд╕реВрд░рдд рд╣реИ, рдПрдХ рдЕрд░реНрдерд╣реАрди рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдпрджрд┐ рдЖрдк рдмрд┐рд▓реНрдХреБрд▓ рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рд╣рд╛рдВ:
my_enable_if
рдФрд░
my_is_signed
рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (
std :: enable_if std :: is_signed
C ++ 11 рдореЗрдВ рдирдП рдереЗ)ред
рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐
C ++ 17 рдХреА рд╢реБрд░реБрдЖрдд рд╣реБрдИ
if constexpr
, рд╕рдВрдХрд▓рд┐рдд рд╕рдордп рдкрд░ рд╢рд░реНрддреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЛрдб рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреА рд╡рд┐рдзрд┐ред рдЕрдЧрд░ рдФрд░ рджреЛрдиреЛрдВ рдмрдпрд╛рдиреЛрдВ рдХреЛ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд░реВрдк рд╕реЗ рд╕рд╣реА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рд╣рд╛рд▓рдд рдХрд╛ рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
template< typename T > T myAbs( T val ) { if constexpr( std::is_signed_v< T > ) { return( ( val <= -1 ) ? -val : val ); } else { if constexpr( std::is_unsigned_v< T > ) { return val; } } }
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░рд╛ рдПрдмреНрд╕ рдлрд╝рдВрдХреНрд╢рди рдЕрдзрд┐рдХ рдХреЙрдореНрдкреИрдХреНрдЯ рдФрд░ рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЧреИрд░-рдЕрдиреБрд░реВрдк рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рд╕реАрдзрд╛ рдирд╣реАрдВ рд╣реИред
static_assert
рдмрд┐рдирд╛ рд╢рд░реНрдд
static_assert
рдЗрд╕ рдХрдерди рдХреЛ рдЦрд░рд╛рдм рд░реВрдк рд╕реЗ рд╕реБрд╕рдВрдЧрдд рдмрдирд╛рддрд╛ рд╣реИ, рдЬреЛ рдорд╛рдирдХ рджреНрд╡рд╛рд░рд╛ рдирд┐рд╖рд┐рджреНрдз рд╣реИ, рднрд▓реЗ рд╣реА рдЗрд╕реЗ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рдП рдпрд╛ рдирд╣реАрдВред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдПрдХ рдЦрд╛рдореА рд╣реИ: рдЯреЗрдореНрдкрд▓реЗрдЯ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдореЗрдВ, рдЧрд┐рд░рд╛рдП рдЧрдП рдСрдкрд░реЗрдЯрд░ рдирд╣реАрдВ рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ рдпрджрд┐ рд╕реНрдерд┐рддрд┐ рдореВрд▓реНрдп рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд╣реИред рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛!
рддреЛ рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХрдорд╛рддреНрд░ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рджреМрд░рд╛рди рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рд╣рдо рдЦрд╛рдХрд╛ рдмрдирд╛рдиреЗ рдХреЗ рд╕рдордп рддрдХ
static_assert
рдХреЗ рдореВрд▓реНрдпрд╛рдВрдХрди рдХреЛ рдЯрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЬрд╛рдПрдЧреА: рдпрджрд┐ рд╣рдорд╛рд░реА рд╕рднреА рд╕реНрдерд┐рддрд┐рдпрд╛рдБ рдЭреВрдареА рд╣реИрдВ рдФрд░ рдХреЗрд╡рд▓ рддрднреА рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд▓реЗрдХрд┐рди рдЬрдм рддрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рддрдм рддрдХ рд╣рдо
static_assert
рдХреЛ рдХреИрд╕реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдЗрд╕рдХреА рд╕реНрдерд┐рддрд┐ рдкреНрд░рдХрд╛рд░ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░реЗрдВ!
template< typename > inline constexpr bool dependent_false_v{ false }; template< typename T > T myAbs( T val ) { if constexpr( std::is_signed_v< T > ) { return( ( val <= -1 ) ? -val : val ); } else { if constexpr( std::is_unsigned_v< T > ) { return val; } else { static_assert( dependent_false_v< T >, "Unsupported type" ); } } }
рднрд╡рд┐рд╖реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд░реАрдм рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдереЛрдбрд╝реА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╕реА ++ 20 рдЕрдВрддрд┐рдо рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд▓рд╛рддрд╛ рд╣реИ: рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ! рдпрд╣ рдЯреЗрдореНрдкрд▓реЗрдЯ (рдФрд░ SFINAE) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмрджрд▓ рджреЗрдЧрд╛ред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ: рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрди рддрд░реНрдХреЛрдВ рдХреЗ рд╕реЗрдЯ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдПрдмреНрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
template< typename T > concept bool Arithmetic() { return std::is_arithmetic_v< T >; }
рдФрд░ рд╣рдо рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдЗрд╕рдХреЗ рддреАрди рддрд░реАрдХреЗ рд╣реИрдВ:
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рддреАрд╕рд░рд╛ рд░реВрдк рдЕрднреА рднреА рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдлрд╝рдВрдХреНрд╢рди рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ! рдпрд╣рд╛рдБ C ++ 20 рдореЗрдВ myAbs рдХрд╛ рдкреВрд░реНрдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:
template< typename T > concept bool Arithmetic() { return std::is_arithmetic_v< T >; } Arithmetic myAbs( Arithmetic val ) { if constexpr( std::is_signed_v< decltype( val ) > ) { return( ( val <= -1 ) ? -val : val ); } else { return val; } } int main() { unsigned int a{ myAbs( 5u ) }; int b{ myAbs< int >( 5u ) };
рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдХреА рдЧрдИ рдХреЙрд▓ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рджреЗрддреА рд╣реИ:
error: cannot call function 'auto myAbs(auto:1) [with auto:1 = const char*]' constraints not satisfied within 'template<class T> concept bool Arithmetic() [with T = const char*]' concept bool Arithmetic(){ ^~~~~~~~~~ 'std::is_arithmetic_v' evaluated to false
рдореИрдВ рд╕рднреА рд╕реЗ рдЖрдЧреНрд░рд╣ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЙрддреНрдкрд╛рджрди рд╡рд┐рдзрд┐ рдореЗрдВ рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рд╕рд╛рд╣рд╕рдкреВрд░реНрд╡рдХ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ; рд╕рдВрдХрд▓рди рд╕рдордп рд░рдирдЯрд╛рдЗрдо рд╕реЗ рд╕рд╕реНрддрд╛ рд╣реИред рд╣реИрдкреНрдкреА SFINAEing!