ุงู„ู…ูุงู‡ูŠู…: ุชุจุณูŠุท ุชู†ููŠุฐ ูุตูˆู„ ุงู„ุฃุฏุงุฉ ุงู„ู…ุณุงุนุฏุฉ STD


ุงู„ู…ูุงู‡ูŠู… ุงู„ุชูŠ ุชุธู‡ุฑ ููŠ C ++ 20 ู‡ูŠ ู…ูˆุถูˆุน ุทูˆูŠู„ ูˆู…ู†ุงู‚ุด ุนู„ู‰ ู†ุทุงู‚ ูˆุงุณุน. ุนู„ู‰ ุงู„ุฑุบู… ู…ู† ูุงุฆุถ ุงู„ู…ูˆุงุฏ ุงู„ู…ุชุฑุงูƒู…ุฉ ุนู„ู‰ ู…ุฑ ุงู„ุณู†ูŠู† (ุจู…ุง ููŠ ุฐู„ูƒ ุฎุทุจ ุงู„ุฎุจุฑุงุก ู…ู† ุงู„ุทุฑุงุฒ ุงู„ุนุงู„ู…ูŠ) ุŒ ู„ุง ูŠุฒุงู„ ู‡ู†ุงูƒ ุฎู„ุท ุจูŠู† ุงู„ู…ุจุฑู…ุฌูŠู† ุงู„ุชุทุจูŠู‚ูŠูŠู† (ุงู„ุฐูŠู† ู„ุง ูŠู†ุงู…ูˆู† ูŠูˆู…ูŠู‹ุง ู…ุน ุงู„ู…ุนูŠุงุฑ) ู…ุง ู‡ูŠ ู…ูุงู‡ูŠู… C ++ 20 ูˆู…ุง ู‡ูŠ ู†ุญุชุงุฌ ุฅุฐุง ูƒุงู† ู‡ู†ุงูƒ enable_if ู…ุญุฏุฏู‹ุง ุนู„ู‰ ู…ุฑ ุงู„ุณู†ูŠู†. ูŠูƒู…ู† ุงู„ุฎุทุฃ ุฌุฒุฆูŠู‹ุง ููŠ ูƒูŠููŠุฉ ุชุทูˆุฑ ุงู„ู…ูุงู‡ูŠู… ุนู„ู‰ ู…ุฏุงุฑ 15 ุนุงู…ู‹ุง ุชู‚ุฑูŠุจู‹ุง (Concepts Full + Concept Map -> Concepts Lite) ุŒ ูˆูŠุฑุฌุน ุฐู„ูƒ ุฌุฒุฆูŠู‹ุง ุฅู„ู‰ ุฃู† ุงู„ู…ูุงู‡ูŠู… ุงุชุถุญ ุฃู†ู‡ุง ุชุฎุชู„ู ุนู† ุงู„ุฃุฏูˆุงุช ุงู„ู…ู…ุงุซู„ุฉ ููŠ ู„ุบุงุช ุฃุฎุฑู‰ (Java / C # bounds generounds ุŒ Rust Rust ุŒ. ..).


ุชุญุช ู…ู‚ุทุน ุงู„ููŠุฏูŠูˆ ูˆู†ุณุฎุฉ ู„ุชู‚ุฑูŠุฑ ุฃุนุฏู‡ ุฃู†ุฏุฑูŠู‡ ุฏุงููŠุฏูˆู ู…ู† ูุฑูŠู‚ ReSharper C ++ ู…ู† ู…ุคุชู…ุฑ C ++ Russia 2019 . ู‚ุงู… ุฃู†ุฏุฑูŠ ุจู…ุฑุงุฌุนุฉ ู…ุฎุชุตุฑุฉ ู„ู„ุงุจุชูƒุงุฑุงุช ุงู„ู…ุชุนู„ู‚ุฉ ุจู…ูู‡ูˆู… C ++ 20 ุŒ ูˆุจุนุฏ ุฐู„ูƒ ุฏุฑุณ ุชู†ููŠุฐ ุจุนุถ ูุฆุงุช ูˆูˆุธุงุฆู STL ุŒ ู…ู‚ุงุฑู†ุฉ ุจูŠู† C ++ 17 ูˆ C ++ 20. ูƒุฐู„ูƒ ุงู„ู‚ุตุฉ ู‡ูŠ ู†ูŠุงุจุฉ ุนู†ู‡.



ู†ุชุญุฏุซ ุนู† ุงู„ู…ูุงู‡ูŠู…. ู‡ุฐุง ู…ูˆุถูˆุน ู…ุนู‚ุฏ ูˆุดุงู…ู„ ุฅู„ู‰ ุญุฏ ู…ุง ุŒ ู„ุฐู„ูƒ ุนู†ุฏ ุงู„ุฅุนุฏุงุฏ ู„ู„ุชู‚ุฑูŠุฑ ุŒ ูƒู†ุช ููŠ ุจุนุถ ุงู„ุตุนูˆุจุงุช. ู‚ุฑุฑุช ุฃู† ุฃู†ุชู‚ู„ ุฅู„ู‰ ุชุฌุฑุจุฉ ุฃุญุฏ ุฃูุถู„ ุงู„ู…ุชุญุฏุซูŠู† ููŠ ู…ุฌุชู…ุน C ++ Andrei Alexandrescu .


ููŠ ู†ูˆูู…ุจุฑ 2018 ุŒ ุฃุซู†ุงุก ุญุฏูŠุซู‡ ููŠ ุงูุชุชุงุญ ุงู„ุงุฌุชู…ุงุน C ++ ุŒ ุณุฃู„ Andrei ุงู„ุฌู…ู‡ูˆุฑ ุนู…ุง ุณุชูƒูˆู† ุนู„ูŠู‡ ุงู„ู…ูŠุฒุฉ ุงู„ูƒุจูŠุฑุฉ ุงู„ุชุงู„ูŠุฉ ู„ู€ C ++:


  • ุงู„ู…ูุงู‡ูŠู…
  • metaclasses
  • ุฃูˆ ุงู„ุชุฃู…ู„ุŸ

ู„ู†ุจุฏุฃ ุจู‡ุฐุง ุงู„ุณุคุงู„. ู‡ู„ ุชุนุชู‚ุฏ ุฃู† ุงู„ู…ูŠุฒุฉ ุงู„ูƒุจูŠุฑุฉ ุงู„ุชุงู„ูŠุฉ ููŠ C ++ ุณุชูƒูˆู† ู…ูุงู‡ูŠู…ุŸ


ูˆูู‚ุง ู„ Alexandrescu ุŒ ุงู„ู…ูุงู‡ูŠู… ู…ู…ู„ุฉ. ู‡ุฐุง ู‡ูˆ ุงู„ุดูŠุก ุงู„ู…ู…ู„ ุงู„ุฐูŠ ุฃู‚ุชุฑุญู‡ ุนู„ูŠูƒ. ุนู„ุงูˆุฉ ุนู„ู‰ ุฐู„ูƒ ุŒ ู…ุง ุฒู„ุช ุบูŠุฑ ู‚ุงุฏุฑ ุนู„ู‰ ุงู„ุญุฏูŠุซ ุงู„ู…ุซูŠุฑ ู„ู„ุงู‡ุชู…ุงู… ูˆุงู„ุญุงุฑ ุนู† ุงู„ู…ุดุงุจูƒ ุŒ ู…ุซู„ Herb Sutter ุŒ ุฃูˆ ุญูˆู„ ุงู„ุชุฃู…ู„ ุŒ ู…ุซู„ Alexandrescu.


ู…ุงุฐุง ู†ุนู†ูŠ ุนู†ุฏู…ุง ู†ุชุญุฏุซ ุนู† ุงู„ู…ูุงู‡ูŠู… ููŠ 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; 

ูˆู„ูƒู† ู…ู† ุงู„ู…ู†ุทู‚ูŠ ุฃู† ูŠุชู… ุฎู„ุท ู…ุนู„ู…ุงุช ุงู„ู‚ุงู„ุจ ุงู„ู†ู…ูˆุฐุฌูŠุฉ ูˆุบูŠุฑ ุงู„ุชู‚ู„ูŠุฏูŠุฉ. ู†ุณู…ูŠ ู†ูˆุนู‹ุง ุตุบูŠุฑู‹ุง ุฅุฐุง ูƒุงู† ุญุฌู…ู‡ ูˆู…ุญุงุฐุงุชู‡ ู„ุง ูŠุชุฌุงูˆุฒุงู† ุงู„ุญุฏูˆุฏ ุงู„ู…ุญุฏุฏุฉ:


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

ุฑุจู…ุง ุŒ ู„ู… ูŠุชุถุญ ุจุนุฏ ุณุจุจ ุญุงุฌุชู†ุง ุฅู„ู‰ ุณูŠุงุฌ ูƒูŠุงู† ุฌุฏูŠุฏ ููŠ ุงู„ู„ุบุฉ ุŒ ูˆู„ู…ุงุฐุง ู‡ุฐุง ุงู„ู…ูู‡ูˆู… ู„ูŠุณ ู…ุฌุฑุฏ ู…ุชุบูŠุฑ 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; ... } 

ุซุงู†ูŠุงู‹ ุŒ ูŠู…ูƒู† ุงุณุชุฎุฏุงู… ุงู„ู…ูุงู‡ูŠู… ุจุฏู„ุงู‹ ู…ู† ุงู„ูƒู„ู…ุงุช ุงู„ุฃุณุงุณูŠุฉ class ุฃูˆ class ุนู†ุฏ ุชุญุฏูŠุฏ ู…ุนู„ู…ุงุช ุงู„ู‚ุงู„ุจ. ุญุฏุฏ ูุฆุฉ optional ุจุณูŠุทุฉ ู…ู† ุดุฃู†ู‡ุง ุจุจุณุงุทุฉ ุชุฎุฒูŠู† ุฒูˆุฌ ู…ู† ุงู„ุนู„ุงู…ุฉ ุงู„ู…ู†ุทู‚ูŠุฉ ุงู„ุชูŠ ุชู…ุช initialized ูˆุงู„ู‚ูŠู…. ูˆุจุทุจูŠุนุฉ ุงู„ุญุงู„ ุŒ ูŠู†ุทุจู‚ ู‡ุฐุง optional ูู‚ุท ุนู„ู‰ ุฃู†ูˆุงุน ุชุงูู‡ุฉ. ู„ุฐู„ูƒ ุŒ ู†ูƒุชุจ Trivial ู‡ู†ุง ูˆุนู†ุฏู…ุง ู†ุญุงูˆู„ ุฅู†ุดุงุก ู…ุซูŠู„ ู…ู† ุดูŠุก ุบูŠุฑ ุชุงูู‡ ุŒ ุนู„ู‰ ุณุจูŠู„ ุงู„ู…ุซุงู„ ุŒ ู…ู† std::string ุŒ ุณูŠูƒูˆู† ู„ุฏูŠู†ุง ุฎุทุฃ ููŠ ุงู„ุชุฑุฌู…ุฉ:


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

ุงู„ู…ูุงู‡ูŠู… ูŠู…ูƒู† ุชุทุจูŠู‚ู‡ุง ุฌุฒุฆูŠุง. ุนู„ู‰ ุณุจูŠู„ ุงู„ู…ุซุงู„ ุŒ ู†ุทุจู‚ ูุฆุฉ ู„ุฏูŠู†ุง ู…ุน ุงู„ุฃู…ุซู„ ุนุงุฒู„ุฉ ุตุบูŠุฑุฉ. ู‚ู… ุจุชุนุฑูŠู ุจู†ูŠุฉ SB (ู…ุฎุฒู† ู…ุคู‚ุช ุตุบูŠุฑ) Size ุซุงุจุช Alignment ุŒ ูˆุณูˆู ู†ู‚ูˆู… ุจุชุฎุฒูŠู† ุงู„ุงุชุญุงุฏ ู…ู† 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 ูŠุดูŠุฑ ุฅู„ู‰ ุชุนุจูŠุฑุงุช ู…ู† ุฃู†ูˆุงุน ู…ุฎุชู„ูุฉ ุŒ ูู…ู† ุงู„ู…ุฑูŠุญ ุจุงู„ู†ุณุจุฉ ู„ู†ุง ุนุฏู… ุชุญุฏูŠุฏ ู†ูˆุน ู‡ุฐู‡ ุงู„ูˆุธูŠูุฉ ุจุดูƒู„ ุตุฑูŠุญ ุŒ ูˆู„ูƒู† ู…ุทุงู„ุจุฉ ุงู„ู…ุชุฑุฌู… ุจุฅุฎุฑุงุฌู‡ุง. ู„ูƒู† ุฅุฐุง ู‚ู…ู†ุง ุจุจุณุงุทุฉ 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...} }; 

ูˆู…ุซุงู„ ู…ุน Comparable . ุฏุนู†ุง ู†ู‚ูˆู„ ุฃู† ุงู„ู†ูˆุน T ู‚ุงุจู„ Comparable ุฅุฐุง ูƒุงู† ูŠู…ูƒู† Comparable ูƒุงุฆู†ูŠู† ู…ู† ุงู„ู†ูˆุน T ุจุงุณุชุฎุฏุงู… ุนุงู…ู„ ุงู„ุชุดุบูŠู„ "ุงู„ุฃู‚ู„" ูˆูŠุชู… ุชุญูˆูŠู„ ุงู„ู†ุชูŠุฌุฉ ุฅู„ู‰ bool . ู‡ุฐุง ุงู„ุณู‡ู… ูˆุงู„ู†ูˆุน ุจุนุฏู‡ ูŠุนู†ูŠ ุฃู† ุชุนุจูŠุฑ ุงู„ูƒุชุงุจุฉ ูŠุชู… ุชุญูˆูŠู„ู‡ ุฅู„ู‰ bool ุŒ ูˆู„ูŠุณ ู…ุณุงูˆูŠุงู‹ ู„ู€ bool :


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

ู…ุง ุฏุฑุณู†ุงู‡ ุจุงู„ูุนู„ ูƒุงูู ู„ุฅุธู‡ุงุฑ ู…ุซุงู„ ูƒุงู…ู„ ู„ุงุณุชุฎุฏุงู… ุงู„ู…ูุงู‡ูŠู….


ู„ุฏูŠู†ุง ุจุงู„ูุนู„ ู…ูู‡ูˆู… ู‚ุงุจู„ Comparable ุŒ ุฏุนูˆู†ุง ู†ุญุฏุฏ ู…ูุงู‡ูŠู… ุงู„ุชูƒุฑุงุฑุงุช. ุฏุนู†ุง ู†ู‚ูˆู„ RandomAccessIterator ู‡ูˆ RandomAccessIterator ูˆุจุนุถ ุงู„ุฎุตุงุฆุต ุงู„ุฃุฎุฑู‰. ู…ุน ู‡ุฐุง ุŒ ู†ุญุฏุฏ ู…ูู‡ูˆู… Sortable . ูŠุณู…ู‰ Range RandomAccess ุฅุฐุง ูƒุงู† ูŠู…ูƒู† ู…ู‚ุงุฑู†ุฉ ู…ูƒุฑุฑ RandomAccess ูˆุนู†ุงุตุฑู‡. ูˆุงู„ุขู† ูŠู…ูƒู†ู†ุง ูƒุชุงุจุฉ ูˆุธูŠูุฉ 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 ุŒ ูุณู†ุญุตู„ ุนู„ู‰ ุฎุทุฃ ุฌูŠุฏ ูˆุตุฏูŠู‚ ู„ู€ 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 ู…ุงูƒุฑูˆ ุŒ Comparable ุฅุนุงุฏุฉ ูƒุชุงุจุฉ Comparable ุจู‡ุฐู‡ ุงู„ุทุฑูŠู‚ุฉ. ู„ู‚ุฏ ุฃุตุจุญ ุฃู‚ุจุญ ู‚ู„ูŠู„ุงู‹ ุŒ ูˆู‡ุฐุง ุชู„ู…ูŠุญุงุช ู„ู†ุง ุงู„ุชูŠ ุชุชุทู„ุจ ุงู„ุชุนุจูŠุฑ ู‡ูˆ ุญู‚ู‹ุง ุดูŠุก ู…ููŠุฏ ูˆู…ู„ุงุฆู…. ู„ุฐู„ูƒ ุญุฏุฏู†ุง ู…ูู‡ูˆู… enable_if ูˆุจุงุณุชุฎุฏุงู… enable_if ุฅู„ู‰ ุฃู† ุฏุงู„ุฉ sort ุชู‚ุจู„ Sortable Range .


ู‚ุฏ ุชุนุชู‚ุฏ ุฃู† ู‡ุฐู‡ ุงู„ุทุฑูŠู‚ุฉ ุชูู‚ุฏ ุงู„ูƒุซูŠุฑ ูˆูู‚ู‹ุง ู„ุฑุณุงุฆู„ ุฎุทุฃ ุงู„ุชุญูˆูŠู„ ุงู„ุจุฑู…ุฌูŠ ุŒ ูˆู„ูƒู† ุŒ ููŠ ุงู„ูˆุงู‚ุน ุŒ ู‡ุฐู‡ ู…ุณุฃู„ุฉ ุฌูˆุฏุฉ ุชุทุจูŠู‚ ุจุฑู†ุงู…ุฌ ุงู„ุชุญูˆูŠู„ ุงู„ุจุฑู…ุฌูŠ. ุฏุนู†ุง ู†ู‚ูˆู„ ุฃู† enable_if ุถุฌุฉ ุญูˆู„ ู‡ุฐุง ุงู„ู…ูˆุถูˆุน ุŒ enable_if ุชุญุฏูŠุฏู‹ุง ุฃู†ู‡ ุฅุฐุง ุงุณุชุจุฏู„ุช enable_if ุงู„ุญุฌุฉ ุงู„ุฃูˆู„ู‰
ุฅุฐุง false ุญุณุงุจ false ุŒ ุซู… ูŠู‚ุฏู…ูˆู† ู‡ุฐุง ุงู„ุฎุทุฃ ุจุญูŠุซ ู„ู… ูŠุชู… ุงู„ูˆูุงุก ุจู‡ุฐุง ุงู„ุดุฑุท.


ุงู„ู…ุซุงู„ ุฃุนู„ุงู‡ ูŠุจุฏูˆ ุฃู†ู‡ ู…ูƒุชูˆุจ ู…ู† ุฎู„ุงู„ ุงู„ู…ูุงู‡ูŠู…. ู„ุฏูŠ ูุฑุถูŠุฉ: ู‡ุฐุง ุงู„ู…ุซุงู„ ุบูŠุฑ ุญุงุณู… ุŒ ู„ุฃู†ู‡ ู„ุง ูŠุณุชุฎุฏู… ุงู„ู…ูŠุฒุฉ ุงู„ุฑุฆูŠุณูŠุฉ ู„ู„ู…ูุงู‡ูŠู… - ูŠุชุทู„ุจ ูู‚ุฑุฉ.


ูŠุชุทู„ุจ ุฌู…ู„ุฉ


ูŠุชุทู„ุจ ุฌู…ู„ุฉ ู…ุซู„ ู‡ุฐุง ุงู„ุดูŠุก ุงู„ุฐูŠ ูŠุฎูŠู… ุชู‚ุฑูŠุจุง ุฃูŠ ุฅุนู„ุงู† ู‚ุงู„ุจ ุฃูˆ ูˆุธูŠูุฉ ุบูŠุฑ ู‚ุงู„ุจ. ุจุดูƒู„ Syntactically ุŒ ูŠุจุฏูˆ ุฃู† ู‡ุฐุง requires ุงู„ูƒู„ู…ุฉ ุงู„ุฃุณุงุณูŠุฉ ุŒ ู…ุชุจูˆุนุฉ ุจุจุนุถ ุชุนุจูŠุฑ Boolean. ูŠุนุฏ ุฐู„ูƒ ุถุฑูˆุฑูŠู‹ุง ู„ุชุตููŠุฉ ุชุฎุตุต ุงู„ู‚ุงู„ุจ ุฃูˆ ู…ุฑุดุญ ุงู„ุชุญู…ูŠู„ ุงู„ุฒุงุฆุฏ ุŒ ุฃูŠ ุฃู†ู‡ ูŠุนู…ู„ ุจู†ูุณ ุทุฑูŠู‚ุฉ ุนู…ู„ 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 ู…ูู‡ูˆู… tautological: ู†ุญู† ู†ุณู…ูŠ 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 ูƒูŠุงู† ุฌุฏูŠุฏ. ูŠุจุฏูˆ ู„ูŠ ุฃู†ู‡ ุณูŠูƒูˆู† ู…ู† ุงู„ู…ู…ูƒู† ุงู„ุงุณุชุบู†ุงุก ุนู† ุฌูˆู‡ุฑ concept ุนู† ุทุฑูŠู‚ ู…ู†ุญ ู…ุชุบูŠุฑุงุช constexpr bool ู…ุน ุฏู„ุงู„ุงุช ุฅุถุงููŠุฉ.
  • ุจู†ุงุก ุฌู…ู„ุฉ ุฎุงุต ู„ุชุทุจูŠู‚ ุงู„ู…ูุงู‡ูŠู…. ุจุงู„ุทุจุน ุŒ ุฅู†ู‡ ู…ู…ุชุน ุŒ ู„ูƒู† ู‡ุฐุง ู…ุฌุฑุฏ ุจู†ุงุก ุฌู…ู„ุฉ. ุฅุฐุง ูƒุงู† ู…ุจุฑู…ุฌูˆ 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> ุŒ ูˆู…ุน ุฐู„ูƒ static_assert ู‡ุฐุง 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 

ูˆู„ูƒู† ู‡ุฐุง ู…ุฌุฑุฏ ู…ุซุงู„ ู…ู…ุชุน. ุจุดูƒู„ ุนุงู… ุŒ ุชุญุชุงุฌ ูู‚ุท ุฅู„ู‰ ุชูˆุฎูŠ ุงู„ุญุฐุฑ.


ุฃู…ุซู„ุฉ ุนู„ู‰ ุงุณุชุฎุฏุงู… ุงู„ู…ูุงู‡ูŠู…


ุชู†ููŠุฐ ูุฆุฉ ุงู„ุฒูˆุฌ


ุนู„ุงูˆุฉ ุนู„ู‰ ุฐู„ูƒ ุŒ ุณุฃุนุฑุถ ุจุนุถ ุฃุฌุฒุงุก STL ุงู„ุชูŠ ูŠู…ูƒู† ุชู†ููŠุฐู‡ุง ููŠ C ++ 17 ุŒ ูˆู„ูƒู† ู…ุฑู‡ู‚ุฉ ุฅู„ู‰ ุญุฏ ู…ุง.
ุซู… ุณู†ุฑู‰ ูƒูŠู ูŠู…ูƒู†ู†ุง ุชุญุณูŠู† ุงู„ุชุทุจูŠู‚ ููŠ C ++ 20.


ู„ู†ุจุฏุฃ ู…ุน ุงู„ุทุจู‚ุฉ pair .
ู‡ุฐู‡ ูุฆุฉ ู‚ุฏูŠู…ุฉ ุฌุฏู‹ุง ุŒ ูู‡ูŠ ู„ุง ุชุฒุงู„ ููŠ ุงู„ุฅุตุฏุงุฑ C ++ 98.
ู„ุง ูŠุญุชูˆูŠ ุนู„ู‰ ุฃูŠ ู…ู†ุทู‚ ู…ุนู‚ุฏ ุŒ ู„ุฐู„ูƒ
ุฃูˆุฏ ุชุนุฑูŠูู‡ ู„ุชุจุฏูˆ ุดูŠุก ู…ู† ู‡ุฐุง ุงู„ู‚ุจูŠู„.
ู…ู† ูˆุฌู‡ุฉ ู†ุธุฑูŠ ุŒ ูŠุฌุจ ุฃู† ูŠู†ุชู‡ูŠ ุชู‚ุฑูŠุจู‹ุง ุจู‡ุฐุง:


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

ูˆู„ูƒู† ุŒ ูˆูู‚ู‹ุง cppreference ุŒ ูŠูˆุฌุฏ ู„ุฏู‰ pair ุงู„ู…ุตู…ู…ูŠู† 8 ู‚ุทุน ูู‚ุท.
ูˆุฅุฐุง ู†ุธุฑุช ุฅู„ู‰ ุงู„ุชุทุจูŠู‚ ุงู„ุญู‚ูŠู‚ูŠ ุŒ ุนู„ู‰ ุณุจูŠู„ ุงู„ู…ุซุงู„ ุŒ ููŠ Microsoft STL ุŒ ุณูŠูƒูˆู† ู‡ู†ุงูƒ ู…ุง ูŠุตู„ ุฅู„ู‰ 15 pair ู„ู„ูุฆุฉ pair . ู„ู† ู†ู†ุธุฑ ุฅู„ู‰ ูƒู„ ู‡ุฐู‡ ุงู„ู‚ูˆุฉ ูˆู†ู‚ุชุตุฑ ุนู„ู‰ ุงู„ู…ูู†ุดุฆ ุงู„ุงูุชุฑุงุถูŠ.


ูŠุจุฏูˆ ุฃู†ู‡ ุดูŠุก ู…ุนู‚ุฏุŸ ุจุงุฏุฆ ุฐูŠ ุจุฏุก ุŒ ู†ุญู† ู†ูู‡ู… ุณุจุจ ุงู„ุญุงุฌุฉ ุฅู„ูŠู‡ุง. ู†ุฑูŠุฏ ุฅุฐุง ูƒุงู†ุช ุฅุญุฏู‰ ูˆุณุงุฆุท ูุฆุฉ 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> ุถู…ู†ูŠู‹ุง:


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

ูŠู…ูƒู†ู†ุง ุงู„ู‚ูŠุงู… ุจุฐู„ูƒ ุŒ ูˆู„ูƒู† ูˆูู‚ู‹ุง ู„ู„ู…ุนุงูŠูŠุฑ ุŒ ูŠุฌุจ ุฃู„ุง ูŠู†ุฌุญ ุงู„ุฃู…ุฑ. ูˆูู‚ู‹ุง ู„ู„ู…ุนุงูŠูŠุฑ ุŒ ูŠุฌุจ ุฃู† ูŠูƒูˆู† ุงู„ุฒูˆุฌ ุงูุชุฑุงุถูŠู‹ุง ุถู…ู†ูŠู‹ุง ู„ูŠุชู… ุฅู†ุดุงุคู‡ ูู‚ุท ุฅุฐุง ูƒุงู† ูƒู„ุง ู…ู† ุนู†ุตุฑูŠู‡ ู…ูุชุฑุถูŠู† ุถู…ู†ูŠู‹ุง ู„ูŠุชู… ุชูƒูˆูŠู†ู‡ู…ุง.


ุณุคุงู„: ู‡ู„ ู†ุญุชุงุฌ ุฅู„ู‰ ูƒุชุงุจุฉ ู…ูู†ุดุฆ ุงู„ุฒูˆุฌ ุงู„ุตุฑูŠุญ ุฃู… ู„ุงุŸ ููŠ C ++ 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 ู„ู„ุญุงู„ุฉ ุนู†ุฏู…ุง ุชูƒูˆู† ุงู„ุนู†ุงุตุฑ ู‚ุงุจู„ุฉ ู„ู„ุชุถู…ูŠู† ุงูุชุฑุงุถูŠู‹ุง ุ›
  • ูˆุงู„ุซุงู†ูŠ ู„ู„ุญุงู„ุฉ ุงู„ู…ุนุงูƒุณุฉ.

ุจุงู„ู…ู†ุงุณุจุฉ ุŒ ู„ุชุทุจูŠู‚ ู†ูˆุน ุงู„ูƒุชุงุจุฉ is_implicitly_default_constructible ููŠ C ++ 17 ุŒ ุฃุนุฑู ู‡ุฐุง ุงู„ุญู„ ุŒ ู„ูƒู†ู†ูŠ ู„ุง ุฃุนุฑู ุงู„ุญู„ ุฏูˆู† 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> ุนู„ู‰ ุฎุทุฃ ููŠ ุงู„ุชุฑุฌู…ุฉ ุŒ ูƒู…ุง ุฃุฑุฏู†ุง:


 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> ู…ู† ุงู„ุฃู‚ูˆุงุณ ุงู„ู…ุนู‚ูˆูุฉ ุงู„ูุงุฑุบุฉ." ุณุชุถูŠู ุฏูˆู„ ู…ุฌู„ุณ ุงู„ุชุนุงูˆู† ุงู„ุฎู„ูŠุฌูŠ ูˆูƒู„ุงู†ุฌ ุฅู„ู‰ ู‡ุฐุง: "ู„ู‚ุฏ ุฌุฑุจู†ุง ู…ุซู„ ู‡ุฐุง ุงู„ู…ู†ุดุฆ ูˆูƒุฐุง ุŒ ู„ู… ูŠุฃุช ุฃูŠ ู…ู†ู‡ู…ุง" ุŒ ูˆุณูŠู‚ูˆู„ุงู† ุณุจุจู‹ุง ู„ูƒู„ ู…ู†ู‡ู…ุง.


ู…ุง ุงู„ู…ุตู…ู…ูŠู† ู„ุฏูŠู†ุง ู‡ู†ุงุŸ ู‡ู†ุงูƒ ู…ู†ุดุฆุงุช ุชู… ุฅู†ุดุงุคู‡ุง ุจูˆุงุณุทุฉ ุจุฑู†ุงู…ุฌ ุงู„ุชุญูˆูŠู„ ุงู„ุจุฑู…ุฌูŠ ู„ู„ู†ุณุฎ ูˆุงู„ุชุญุฑูƒ ุŒ ูˆู‡ู†ุงูƒ ุจุนุถ ู…ุง ูƒุชุจู‡ ู„ู†ุง. ู…ุน ุงู„ู†ุณุฎ ูˆุงู„ุชุญุฑูŠูƒ ุŒ ูƒู„ ุดูŠุก ุจุณูŠุท: ูŠุชูˆู‚ุนูˆู† ู…ุนู„ู…ุฉ ูˆุงุญุฏุฉ ุŒ ู†ู…ุฑ ุตูุฑุงู‹. ุจุงู„ู†ุณุจุฉ ุฅู„ู‰ ุงู„ู…ู†ุดุฆ ุงู„ุฎุงุต ุจู†ุง ุŒ ุงู„ุณุจุจ ู‡ูˆ ุฃู† ุงู„ุฅุญู„ุงู„ ู…ุฑู†.


ุชู‚ูˆู„ ุฏูˆู„ ู…ุฌู„ุณ ุงู„ุชุนุงูˆู† ุงู„ุฎู„ูŠุฌูŠ: "ูุดู„ ุงู„ุงุณุชุจุฏุงู„ ุŒ ุญุงูˆู„ ุงู„ุนุซูˆุฑ ุนู„ู‰ ู†ูˆุน type ุฏุงุฎู„ enable_if<false> - ุชุนุฐุฑ ุงู„ุนุซูˆุฑ ุนู„ูŠู‡ ุŒ ุขุณู."


ูŠุนุชุจุฑ ูƒู„ุงู†ุฌ ู‡ุฐุง ุงู„ูˆุถุน ุญุงู„ุฉ ุฎุงุตุฉ. ู„ุฐู„ูƒ ุŒ ุงู†ู‡ ุฑุงุฆุน ุฌุฏุง ูŠุธู‡ุฑ ู‡ุฐุง ุงู„ุฎุทุฃ. ุฅุฐุง ุญุตู„ู†ุง ุนู„ู‰ false ุนู†ุฏ ุชู‚ูŠูŠู… enable_if ุงู„ุฃูˆู„ู‰ ุŒ ูŠูƒุชุจ ุฃู† ุงู„ุดุฑุท ุงู„ู…ุญุฏุฏ ุบูŠุฑ 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 ุณุงุจู‚ู‹ุง ุฏุงุฎู„ enable_if ุŒ 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/ar467299/


All Articles