рдХреИрд╕реЗ SFINAE рдЪрд┐рдХрдирд╛ рдФрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП

рдлрд┐рд░ рд╕реЗ рдирдорд╕реНрдХрд╛рд░ред рд╣рдо рдЖрдкрдХреЗ рд╕рд╛рде рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рд▓реЗрдЦ рд╕рд╛рдЭрд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдПрдХ рдЕрдиреБрд╡рд╛рдж рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкрд╛рдареНрдпрдХреНрд░рдо "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() { //int a{ myAbs( 5u ) }; int b{ myAbs< int >( 5u ) }; //int c{ myAbs< unsigned int, true >( 5u ) }; } 

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

 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 рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ рдорд╛рдирдХ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рдмреАрдЪ рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреА рдХреНрд░рд┐рдпрд╛рд╢реАрд▓рддрд╛ рд╣реИ:

 //C++11 template< typename T > using IsSigned = typename std::enable_if< std::is_signed< T >::value, bool >::type; //C++14 - std::enable_if_t template< typename T > using IsSigned = std::enable_if_t< std::is_signed< T >::value, bool >; //C++17 - std::is_signed_v template< typename T > using IsSigned = std::enable_if_t< std::is_signed_v< T >, bool >; 

рд▓реЗрдХрд┐рди рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд╣реА рд░рд╣рддрд╛ рд╣реИ:

 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; } /*else { static_assert( false, "T must be signed or unsigned arithmetic type." ); }*/ } } 

рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░рд╛ рдПрдмреНрд╕ рдлрд╝рдВрдХреНрд╢рди рдЕрдзрд┐рдХ рдХреЙрдореНрдкреИрдХреНрдЯ рдФрд░ рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЧреИрд░-рдЕрдиреБрд░реВрдк рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рд╕реАрдзрд╛ рдирд╣реАрдВ рд╣реИред 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 >; } 

рдФрд░ рд╣рдо рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдЗрд╕рдХреЗ рддреАрди рддрд░реАрдХреЗ рд╣реИрдВ:

 //   template< typename T > requires Arithmetic< T >() T myAbs( T val ); //   template< Arithmetic T > T myAbs( T val ); //  Arithmetic myAbs( Arithmetic val ); 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рддреАрд╕рд░рд╛ рд░реВрдк рдЕрднреА рднреА рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдлрд╝рдВрдХреНрд╢рди рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ! рдпрд╣рд╛рдБ 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 ) }; //std::string c{ myAbs( "d" ) }; } 

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдХреА рдЧрдИ рдХреЙрд▓ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рджреЗрддреА рд╣реИ:

 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!

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


All Articles