C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- å鿍¡æ¿(C++14 èµ·)
- æ´æ°åé¢é
- èååå§å
- æ¯è¾è¿ç®ç¬¦
- é»è®¤æ¯è¾(C++20 èµ·)
- 转ä¹åºå
- for 循ç¯
- while 循ç¯
- ç¨æ·å®ä¹è½¬æ¢
- SFINAE
- 䏻彿°
- ASCII ç 表
- æ è¯ç¬¦
- ç±»å
- å 忍¡å
- 对象
- åºæ¬æ¦å¿µ
- 表达å¼
- 声æ
- åå§å
- 彿°
- è¯å¥
- ç±»
- è¿ç®ç¬¦éè½½
- 模æ¿
- å¼å¸¸
- äºå¡æ§å å
- å ä½ç¬¦ç±»å说æç¬¦ (C++11 èµ·)
- decltype 说æç¬¦
- 彿°å£°æ
- final 说æç¬¦ (C++11 èµ·)
- override 说æç¬¦(C++11 èµ·)
- å¼ç¨å£°æ
- ç§»å¨æé 彿°
- ç§»å¨èµå¼è¿ç®ç¬¦
- æä¸¾å£°æ
- constexpr 说æç¬¦(C++11 èµ·)
- å表åå§å (C++11 èµ·)
- æé 彿°ä¸æååå§åå¨å表
- using 声æ
- nullptrï¼æéåé¢é
- åºç¡ç±»å
- ç±»åå«åï¼å«å模ç (C++11 èµ·)
- å½¢åå
- èåä½å£°æ
- å符串åé¢é
- ç¨æ·å®ä¹åé¢é (C++11 èµ·)
- 屿§è¯´æç¬¦åºå(C++11 èµ·)
- Lambda è¡¨è¾¾å¼ (C++11 èµ·)
- noexcept 说æç¬¦ (C++11 èµ·)
- noexcept è¿ç®ç¬¦ (C++11 èµ·)
- alignof è¿ç®ç¬¦(C++11 èµ·)
- alignas 说æç¬¦ (C++11 èµ·)
- åå¨ç±»è¯´æç¬¦
- åºäºèå´ç for å¾ªç¯ (C++11 èµ·)
- static_assert 声æ
- éå¼è½¬æ¢
- 代ç¨è¿ç®ç¬¦è¡¨ç¤º
- èªå¢/èªåè¿ç®ç¬¦
- æå 表达å¼(C++17 èµ·)
- 类模æ¿å®åæ¨å¯¼(C++17 èµ·)
- 模æ¿å½¢å䏿¨¡æ¿å®å
- if è¯å¥
- inline 说æç¬¦
- ç»æåç»å®å£°æ (C++17 èµ·)
- switch è¯å¥
- å符åé¢é
- å½å空é´
- æ±å¼é¡ºåº
- å¤å¶æ¶é¤
- consteval 说æç¬¦ (C++20 èµ·)
- constinit 说æç¬¦ (C++20 èµ·)
- åç¨ (C++20)
- 模å (C++20 èµ·)
- 约æä¸æ¦å¿µ (C++20 èµ·)
- new 表达å¼
- do-while 循ç¯
- continue è¯å¥
- break è¯å¥
- goto è¯å¥
- return è¯å¥
- 卿å¼å¸¸è¯´æ
- throw 表达å¼
- try å
- å½å空é´å«å
- 类声æ
- cvï¼const ä¸ volatileï¼ç±»åéå®ç¬¦
- é»è®¤åå§å
- å¼åå§å(C++03 èµ·)
- é¶åå§å
- å¤å¶åå§å
- ç´æ¥åå§å
- 常éåå§å
- å¼ç¨åå§å
- å¼ç±»å«
- C++ è¿ç®ç¬¦ä¼å 级
- å¸å°åé¢é
- æµ®ç¹åé¢é
- typedef 说æç¬¦
- æ¾å¼ç±»å转æ¢
- static_cast 转æ¢
- dynamic_cast 转æ¢
- const_cast 转æ¢
- reinterpret_cast 转æ¢
- delete 表达å¼
- æé 彿°ä¸æååå§åå¨å表
- this æé
- 访é®è¯´æç¬¦
- åå 声æ
- virtual 彿°è¯´æç¬¦
- explicit 说æç¬¦
- éææå
- é»è®¤æé 彿°
- å¤å¶æé 彿°
- å¤å¶èµå¼è¿ç®ç¬¦
- ææå½æ°
- 类模æ¿
- 彿°æ¨¡æ¿
- æ¾å¼ï¼å ¨ï¼æ¨¡æ¿ç¹å
- æ±ç¼å£°æ
- C++ çåå²
- ä½ç¨å
- çåæ
- å®ä¹ä¸åä¸å®ä¹è§åï¼ODRï¼
- å忥æ¾
- æéå®çå忥æ¾
- æ éå®çå忥æ¾
- å¦åè§å
- æªå®ä¹è¡ä¸º
- ç¿»è¯é¶æ®µ
- 常é表达å¼
- èµå¼è¿ç®ç¬¦
- ç®æ¯è¿ç®ç¬¦
- é»è¾è¿ç®ç¬¦
- æå访é®è¿ç®ç¬¦
- å ¶ä»è¿ç®ç¬¦
- sizeof è¿ç®ç¬¦
- typeid è¿ç®ç¬¦
- æé声æ
- æ°ç»å£°æ
- è¯è¨é¾æ¥
- 详述类å说æç¬¦
- é»è®¤å®å
- åé¿å®å
- å®åä¾èµæ¥æ¾
- éè½½å³è®®
- éè½½å½æ°çå°å
- æ³¨å ¥ç±»å
- ééææ°æ®æå
- ééææå彿°
- åµå¥ç±»
- æ´¾çç±»
- 空åºç±»ä¼å
- æ½è±¡ç±»
- ä½å
- è½¬æ¢æé 彿°
- æå模æ¿
- 模æ¿å®åæ¨å¯¼
- é¨å模æ¿ç¹å
- sizeof... è¿ç®ç¬¦
- å¾ å³å
- 彿° try å
- æ©å å½åç©ºé´ std
- åæ¯ç¼©å
- RAII
- ä¸/äº/é¶ä¹æ³å
- PImpl
- é¶å¼éåå
- ç±»å
- éå¼è½¬æ¢
- 注é
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >C++ è¯è¨ > 约æä¸æ¦å¿µ (C++20 èµ·)
约æä¸æ¦å¿µ (C++20 èµ·)
类模æ¿ï¼å½æ°æ¨¡æ¿ï¼ä»¥å鿍¡æ¿å½æ°ï¼å¸¸ä¸ºç±»æ¨¡æ¿çæåï¼ï¼å¯ä»¥ä¸çº¦æï¼constraintï¼å ³èï¼å®æå®å¯¹æ¨¡æ¿å®åçä¸äºè¦æ±ï¼è¿äºè¦æ±å¯è¢«ç¨äºéæ©ææ°å½ç彿°éè½½åæ¨¡æ¿ç¹åã
è¿ç§è¦æ±çå ·åéå被称为æ¦å¿µï¼conceptï¼ãæ¯ä¸ªæ¦å¿µé½æ¯è°è¯ï¼äºç¼è¯æ¶æ±å¼ï¼å¹¶æä¸ºä»¥ä¹ä½ä¸ºä¸é¡¹çº¦æçæ¨¡æ¿æ¥å£çä¸é¨åï¼
#include <string> #include <cstddef> #include <concepts> using namespace std::literals;  // æ¦å¿µ "Hashable" ç声æï¼å¯è¢«ç¬¦å以䏿¡ä»¶çä»»ä½ç±»å T æ»¡è¶³ï¼ // å¯¹äº T ç±»åçå¼ aï¼è¡¨è¾¾å¼ std::hash<T>{}(a) å¯ç¼è¯ä¸å ¶ç»æå¯è½¬æ¢ä¸º std::size_t template<typename T> concept Hashable = requires(T a) { { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>; };  struct meow {};  template<Hashable T> void f(T); // å约æç C++20 彿°æ¨¡æ¿  // åºç¨ç¸å约æçå¦ä¸ç§æ¹å¼ï¼ // template<typename T> // requires Hashable<T> // void f(T); // // template<typename T> // void f(T) requires Hashable<T>;  int main() { f("abc"s); // OKï¼std::string 满足 Hashable f(meow{}); // é误ï¼meow 䏿»¡è¶³ Hashtable }
å¨ç¼è¯æ¶æ£æµçº¦æè¿è§ï¼å¨æ¨¡æ¿å®ä¾åè¿ç¨çæ©æè¿è¡ï¼è¿å¯¼è´éè¯¯ä¿¡æ¯æ´æçè§£ã
std::list<int> l = {3,-1,10}; std::sort(l.begin(), l.end()); //æ æ¦å¿µçå ¸åç¼è¯å¨è¯æï¼ // invalid operands to binary expression ('std::_List_iterator<int>' and // 'std::_List_iterator<int>') // std::__lg(__last - __first) * 2); // ~~~~~~ ^ ~~~~~~~ // â¦â¦ 50 è¡è¾åºâ¦â¦ // //ææ¦å¿µçå ¸åç¼è¯å¨è¯æï¼ // error: cannot call std::sort with std::_List_iterator<int> // note: concept RandomAccessIterator<std::_List_iterator<int>> was not satisfied
æ¦å¿µçç®çæ¯å¡é è¯ä¹åç±»ï¼NumberãRangeãRegularFunctionï¼èéè¯æ³ä¸çéå¶ï¼HasPlusãArrayï¼ãæç § ISO C++ æ ¸å¿æ¹é T.20 æè¯´ï¼âä¸è¯æ³éå¶ç¸åï¼æå®ææä¹è¯ä¹çè½åæ¯çæ£çæ¦å¿µçå³å®æ§ç¹å¾ãâ
æ¦å¿µ
æ¦å¿µæ¯è¦æ±çå ·åéåãæ¦å¿µçå®ä¹å¿ é¡»åºç°äºå½å空é´ä½ç¨åä¸ã
æ¦å¿µå®ä¹æ¥æä»¥ä¸å½¢å¼
template < 模æ¿å½¢åå表 >
|
|||||||||
// æ¦å¿µ template <class T, class U> concept Derived = std::is_base_of<U, T>::value;
æ¦å¿µä¸è½éå½å°æåèªèº«ï¼èä¸ä¸è½å约æï¼
template<typename T> concept V = V<T*>; // é误ï¼éå½çæ¦å¿µ  template<class T> concept C1 = true; template<C1 T> concept Error1 = true; // é误ï¼C1 T è¯å¾çº¦ææ¦å¿µå®ä¹ template<class T> requires C1<T> concept Error2 = true; // é误ï¼requires åå¥è¯å¾çº¦ææ¦å¿µ
ä¸å 许æ¦å¿µçæ¾å¼å®ä¾åãæ¾å¼ç¹åæé¨åç¹åï¼ä¸è½æ´æ¹çº¦æçååå®ä¹çæä¹ï¼ã
约æ
çº¦ææ¯é»è¾æä½åæä½æ°çåºåï¼å®æå®å¯¹äºæ¨¡æ¿å®åçè¦æ±ãå®ä»¬å¯å¨ requires 表达å¼ï¼è§ä¸æï¼ä¸åºç°ï¼ä¹å¯ç´æ¥ä½ä¸ºæ¦å¿µç主ä½ã
æä¸ç§ç±»åç约æï¼
对å å«éµå¾ªä»¥ä¸é¡ºåºçæä½æ°çé»è¾ä¸è¡¨è¾¾å¼è¿è¡è§èåï¼ç¡®å®ä¸ä¸ä¸ªå£°æå ³èç约æï¼
- æ¯ä¸ªåçº¦ææ¨¡æ¿å½¢åæå¼å ¥ç约æè¡¨è¾¾å¼ï¼æåºç°é¡ºåºï¼
- 模æ¿å½¢åå表ä¹åç requires åå¥ä¸ç约æè¡¨è¾¾å¼ï¼
- å°¾éç requires åå¥ä¸ç约æè¡¨è¾¾å¼ã
è¿ä¸ªé¡ºåºå³å®äºå¨æ£æ¥æ¯å¦æ»¡è¶³æ¶å个约æçå®ä¾å顺åºã
å约æç声æåªè½ä»¥ç¸åçè¯æ³å½¢å¼é声æãä¸è¦æ±è¯æã
template<Incrementable T> void f(T) requires Decrementable<T>;  template<Incrementable T> void f(T) requires Decrementable<T>; // OKï¼é声æ  template<typename T> requires Incrementable<T> && Decrementable<T> void f(T); // éè¯æï¼ä¸è¦æ±è¯æ  // ä¸åä¸¤ä¸ªå£°ææ¥æä¸åç约æï¼ // 第ä¸å£°ææ¥æ Incrementable<T> && Decrementable<T> // 第äºå£°ææ¥æ Decrementable<T> && Incrementable<T> // 尽管å®ä»¬é»è¾ä¸çä»·  template<Incrementable T> void g() requires Decrementable<T>;  template<Decrementable T> void g() requires Incrementable<T>; // éè¯æï¼ä¸è¦æ±è¯æ
åå
两个约æçååï¼æ¯éè¿å¨çº¦æè¡¨è¾¾å¼ä¸ä½¿ç¨ && è¿ç®ç¬¦æ¥ææçï¼
template <class T> concept Integral = std::is_integral<T>::value; template <class T> concept SignedIntegral = Integral<T> && std::is_signed<T>::value; template <class T> concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
两个约æçååï¼ä» å½ä¸¤ä¸ªçº¦æåè¢«æ»¡è¶³æ¶æå¾å°æ»¡è¶³ãååä»å·¦å°å³æ±å¼ä¸ä¸ºçè·¯æ±å¼ï¼è¥ä¸æ»¡è¶³å·¦ä¾§çº¦æï¼åä¸å°è¯å¯¹å³ä¾§çº¦æè¿è¡æ¨¡æ¿å®åæ¿æ¢ï¼è¿é²æ¢åºç°ç«å³è¯å¢å¤çæ¿æ¢æå¯¼è´ç失败ï¼ã
template<typename T> constexpr bool get_value() { return T::value; }  template<typename T> requires (sizeof(T) > 1 && get_value<T>()) void f(T); // #1  void f(int); // #2  void g() { f('A'); // OKï¼è°ç¨ #2ã彿£æ¥ #1 ççº¦ææ¶ï¼ // 䏿»¡è¶³ 'sizeof(char) > 1'ï¼æ 䏿£æ¥ get_value<T>() }
æå
两个约æçæåï¼æ¯éè¿å¨çº¦æè¡¨è¾¾å¼ä¸ä½¿ç¨ || è¿ç®ç¬¦æ¥ææçï¼
è¥ä»»ä¸çº¦æå¾å°æ»¡è¶³ï¼å两个约æçæåçå°æ»¡è¶³ãæåä»å·¦å°å³æ±å¼ä¸ä¸ºçè·¯æ±å¼ï¼è¥æ»¡è¶³å·¦ä¾§çº¦æï¼åä¸å°è¯å¯¹å³ä¾§çº¦æè¿è¡æ¨¡æ¿å®åæ¿æ¢ï¼ã
template <class T = void> requires EqualityComparable<T> || Same<T, void> struct equal_to;
åå约æ
åå约æç±ä¸ä¸ªè¡¨è¾¾å¼ Eï¼åä¸ä¸ªä» E å
åºç°ç忍¡æ¿å½¢åå°ï¼å¯¹å约æå®ä½ç忍¡æ¿å½¢åçæææ¶åçï¼å模æ¿å®åçæ å°ç»æãè¿ç§æ å°è¢«ç§°ä½å
¶å½¢åæ å°ã
åå约æå¨çº¦æè§èåè¿ç¨ä¸å½¢æãE å§ç»ä¸æ¯é»è¾ä¸ï¼ANDï¼æè
é»è¾æï¼ORï¼è¡¨è¾¾å¼ï¼å®ä»¬å嫿ææååååï¼ã
对ååçº¦ææ¯å¦æ»¡è¶³çæ£æ¥ï¼æ¯éè¿å¨è¡¨è¾¾å¼ E 䏿¿æ¢å
¶å½¢åæ å°åå个模æ¿å®åæ¥è¿è¡çãè¥æ¿æ¢äº§çäºæ æçç±»åæè¡¨è¾¾å¼ï¼åçº¦ææªè½æ»¡è¶³ãå¦åï¼å¨ä»»ä½å·¦å¼å°å³å¼è½¬æ¢åï¼E åºå½ä¸º bool ç±»åç纯å³å¼å¸¸é表达å¼ï¼å½ä¸ä»
å½å®æ±å¼ä¸º true æ¶è¯¥çº¦æå¾ä»¥æ»¡è¶³ã
E 卿¿æ¢åçç±»åå¿
é¡»ä¸¥æ ¼ä¸º boolãä¸å®¹è®¸ä»»ä½è½¬æ¢ï¼
template<typename T> struct S { constexpr operator bool() const { return true; } };  template<typename T> requires (S<T>{}) void f(T); // #1  void f(int); // #2  void g() { f(0); // éè¯¯ï¼æ£æ¥ #1 æ¶ S<int>{} ä¸å ·æ bool ç±»åï¼ // 尽管 #2 æ¯è¾ä¼å¹é }
è¥ä¸¤ä¸ªåå约æç±å¨æºç å±é¢ä¸ç¸åç表达å¼ç»æï¼ä¸å®ä»¬çå½¢åæ å°çä»·ï¼å认为å®ä»¬çåã
template<class T> constexpr bool is_meowable = true; template<class T> constexpr bool is_cat = true;  template<class T> concept Meowable = is_meowable<T>;  template<class T> concept BadMeowableCat = is_meowable<T> && is_cat<T>;  template<class T> concept GoodMeowableCat = Meowable<T> && is_cat<T>;  template<Meowable T> void f1(T); // #1  template<BadMeowableCat T> void f1(T); // #2  template<Meowable T> void f2(T); // #3  template<GoodMeowableCat T> void f2(T); // #4  void g(){ f1(0); // éè¯¯ï¼æ§ä¹ï¼ // BadMeowableCat å Meowable ä¸ç is_meowable<T> // ææäºæåºå«çåå约æä¸å®ä»¬å¹¶ä¸çåï¼æ å®ä»¬ä¸å½¼æ¤å å«ï¼  f2(0); // OKï¼è°ç¨ #4ï¼æ¯ #3 æ´å约æ // GoodMeowableCat ä» Meowable è·å¾å ¶ is_meowable<T> }
约æè§èå
约æè§è忝å°ä¸ä¸ªçº¦æè¡¨è¾¾å¼åæ¢ä¸ºä¸ä¸ªåå约æçåå䏿åçåºåçè¿ç¨ã表达å¼çèå¼å®ä¹å¦ä¸ï¼
- è¡¨è¾¾å¼ (E) çèå¼å°±æ¯ E çèå¼ï¼
- è¡¨è¾¾å¼ E1 && E2 çè弿¯ E1 å E2 èå¼çååï¼
- è¡¨è¾¾å¼ E1 || E2 çè弿¯ E1 å E2 èå¼çæåï¼
- è¡¨è¾¾å¼ C<A1, A2, ... , AN>ï¼å
¶ä¸
Cæåæä¸ªæ¦å¿µï¼çèå¼ï¼æ¯ä»¥ A1, A2, ... , AN 对 C çæ¯ä¸ªåå约æçå½¢åæ å°ä¸çCçå¯¹åºæ¨¡æ¿å½¢åè¿è¡æ¿æ¢ä¹åï¼Cç约æè¡¨è¾¾å¼çèå¼ãè¥ä»»ä½è¿ç§å½¢åæ å°ä¸çæ¿æ¢äº§çäºæ æçç±»åæè¡¨è¾¾å¼ï¼åç¨åºéè¯æï¼ä¸è¦æ±è¯æã
template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; // OKï¼è§èå为以ä¸å项çæå // - T::valueï¼æ å°ä¸º T -> U*ï¼å // - trueï¼æç©ºæ å°ï¼ã // æ å°ä¸æ²¡ææ æç±»åï¼å°½ç®¡ T::value å¯¹æææéç±»ååéè¯æ  template<typename V> concept C = B<V&>; // è§èå为以ä¸çæå // - T::valueï¼æ å°ä¸º T-> V&*ï¼å // - trueï¼æç©ºæ å°ï¼ã // æ å°ä¸ææäºæ æç±»å V&* => éè¯æï¼ä¸è¦æ±è¯æ
- ä»»ä½å
¶ä»è¡¨è¾¾å¼ E çè弿¯ä¸æ¡åå约æï¼å
¶è¡¨è¾¾å¼ä¸º E èå
¶å½¢åæ å°ä¸ºæçæ å°ãè¿å
æ¬æææå 表达å¼ï¼çè³å
æ¬ä»¥
&&æ||è¿ç®ç¬¦è¿è¡çæå ã
&& æ || çç¨æ·å®ä¹éè½½å¨çº¦æè§èå䏿 ææã
requires åå¥
å ³é®è¯ requires ç¨äºå¼å ¥ requires åå¥ï¼å®æå®å¯¹å模æ¿å®åï¼æå¯¹å½æ°å£°æç约æã
template<typename T> void f(T&&) requires Eq<T>; // å¯ä½ä¸ºå½æ°å£°æç¬¦çææ«å ç´ åºç°  template<typename T> requires Addable<T> // æå¨æ¨¡æ¿å½¢åå表çå³è¾¹ T add(T a, T b) { return a + b; }
è¿ç§æ åµä¸ï¼å ³é®è¯ requires å¿ é¡»åéæä¸ªå¸¸é表达å¼ï¼æ å¯ä»¥å为 requires trueï¼ï¼ä½å ¶æå¾æ¯ä½¿ç¨æä¸ªå ·åæ¦å¿µï¼å¦ä¸ä¾ï¼ï¼æå ·åæ¦å¿µç䏿¡åå/æåï¼æä¸ä¸ª requires 表达å¼ã
表达å¼å¿ é¡»å ·æä¸åå½¢å¼ä¹ä¸ï¼
- åç表达å¼ï¼ä¾å¦ Swappable<T>ãstd::is_integral<T>::valueã(std::is_object_v<Args> && ...) æä»»ä½å¸¦æ¬å·è¡¨è¾¾å¼
- 以è¿ç®ç¬¦
&&èç»çåç表达å¼çåºå - 以è¿ç®ç¬¦
||èç»çå述表达å¼çåºå
template<class T> constexpr bool is_meowable = true;  template<class T> constexpr bool is_purrable() { return true; }  template<class T> void f(T) requires is_meowable<T>; // OK  template<class T> void g(T) requires is_purrable<T>(); // é误ï¼is_purrable<T>() 䏿¯åçè¡¨è¾¾å¼ Â template<class T> void h(T) requires (is_purrable<T>()); // OK
requires 表达å¼
å
³é®è¯ requires 亦ç¨äºå¼å§ä¸ä¸ª requires 表达å¼ï¼å®æ¯ bool ç±»åç纯å³å¼è¡¨è¾¾å¼ï¼æè¿°å¯¹ä¸äºæ¨¡æ¿å®åç约æãè¥çº¦æå¾å°æ»¡è¶³åè¿ç§è¡¨è¾¾å¼ä¸º trueï¼å¦å为 falseï¼
template<typename T> concept Addable = requires (T x) { x + x; }; // requires è¡¨è¾¾å¼ Â template<typename T> requires Addable<T> // requires åå¥ï¼é requires è¡¨è¾¾å¼ T add(T a, T b) { return a + b; }  template<typename T> requires requires (T x) { x + x; } // éå³ç约æï¼æ³¨æå ³é®å被使ç¨ä¸¤æ¬¡ T add(T a, T b) { return a + b; }
requires 表达å¼çè¯æ³å¦ä¸ï¼
requires ( å½¢åå表(å¯é) ) { è¦æ±åºå }
|
|||||||||
| å½¢åå表 | - | ä¸å½æ°å£°æä¸ç±»ä¼¼çå½¢åçéå·åéå表ï¼ä½ä¸å
许é»è®¤å®åä¸ä¸è½ä»¥ï¼å¹¶éæå®å
å±å¼çï¼çç¥å·ç»å°¾ãè¿äºå½¢åæ å卿ãè¿æ¥æçåæï¼å®ä»¬ä»
ç¨äºè¾
å©è¿è¡åä¸ªè¦æ±çå¶å®ãè¿äºå½¢åå¨ è¦æ±åºå çé } åå¤äºä½ç¨åä¸ã
|
| è¦æ±åºå | - | è¦æ±ï¼requirementï¼çåºåï¼æè¿°äºä¸ï¼æ¯ä¸ªè¦æ±ä»¥åå·ç»å°¾ï¼ã |
è¦æ±åºå ä¸çæ¯ä¸ªè¦æ±æ¯ä¸åä¹ä¸ï¼
- ç®åè¦æ±ï¼simple requirementï¼
- ç±»åè¦æ±ï¼type requirementï¼
- å¤åè¦æ±ï¼compound requirementï¼
- åµå¥è¦æ±ï¼nested requirementï¼
è¦æ±å¯ä»¥æåå¤äºä½ç¨åä¸ç模æ¿å½¢åï¼æåç± å½¢åå表 å¼å ¥çå±é¨å½¢åï¼ææåä»å ¶å¤å´è¯å¢ä¸å¯è§çä»»ä½å ¶ä»å£°æã
对模æ¿åå®ä½ç声æä¸æä½¿ç¨ç requires 表达å¼è¿è¡æ¨¡æ¿å®åæ¿æ¢ï¼å¯è½å¯¼è´å¨å ¶è¦æ±ä¸å½¢ææ æçç±»åæè¡¨è¾¾å¼ï¼æè¿åè¿äºè¦æ±çè¯ä¹çº¦æãè¿äºæ åµä¸ï¼è¯¥ requires è¡¨è¾¾å¼æ±å¼ä¸º false èä¸å¯¼è´ç¨åºéè¯æãæ¿æ¢åè¯ä¹çº¦ææ£æ¥æè¯æ³é¡ºåºæ§è¡ï¼å¹¶å¨éå°ç¡®å® requires 表达å¼ç»æçæ¡ä»¶æ¶åæ¢ãè¥æ¿æ¢ï¼è¥åå¨ï¼åè¯ä¹çº¦ææ£æ¥æåï¼å requires è¡¨è¾¾å¼æ±å¼ä¸º trueã
å¦æå¯¹äºæ¯ä¸ç§å¯è½ç模æ¿å®å requires 表达å¼ä¸é½ä¼åºç°æ¿æ¢å¤±è´¥ï¼åç¨åºéè¯æï¼ä¸è¦æ±è¯æï¼
template<class T> concept C = requires { new int[-(int)sizeof(T)]; // 对æ¯ä¸ª T åä¸ºæ æï¼éè¯æï¼ä¸è¦æ±è¯æ };
è¥ requires 表达å¼å¨å ¶çº¦æä¸å«ææ æç±»åæè¡¨è¾¾å¼ï¼èå®å¹¶éåºç°äºæ¨¡æ¿åå®ä½ç声æä¹å ï¼åç¨åºéè¯æã
ç®åè¦æ±
ç®åè¦æ±æ¯ä»»æè¡¨è¾¾å¼è¯å¥ã宿è¨è¯¥è¡¨è¾¾å¼åæ³ãè¯¥è¡¨è¾¾å¼æ¯ä¸æ±å¼æä½æ°ï¼åªæ£æ¥è¯è¨æ£ç¡®æ§ã
template<typename T> concept Addable = requires (T a, T b) { a + b; // âè¡¨è¾¾å¼ a + b æ¯å¯ç¼è¯çåæ³è¡¨è¾¾å¼â };  template <class T, class U = T> concept Swappable = requires(T&& t, U&& u) { swap(std::forward<T>(t), std::forward<U>(u)); swap(std::forward<U>(u), std::forward<T>(t)); };
ç±»åè¦æ±
ç±»åè¦æ±æ¯å ³é®è¯ typename åéä¸ä¸ªç±»ååï¼å¯éå°æéå®ãå ¶è¦æ±æ¯è¯¥ç±»åååæ³ï¼è¿å¯ç¨äºæ ¡éªæä¸ªå ·ååµå¥ç±»ååå¨ï¼ææä¸ªç±»æ¨¡æ¿ç¹åæåä¸ä¸ªç±»åï¼ææä¸ªå«å模æ¿ç¹åæåä¸ä¸ªç±»åãæå类模æ¿ç¹åçç±»åè¦æ±ä¸è¦æ±è¯¥ç±»å宿´ã
template<typename T> using Ref = T&; template<typename T> concept C = requires { typename T::inner; // è¦æ±çåµå¥æåå typename S<T>; // è¦æ±ç类模æ¿ç¹å typename Ref<T>; // è¦æ±çå«åæ¨¡æ¿æ¿æ¢ };  template <class T, class U> using CommonType = std::common_type_t<T, U>; template <class T, class U> concept Common = requires (T t, U u) { typename CommonType<T, U>; // CommonType<T, U> 忳并æåä¸ä¸ªç±»å { CommonType<T, U>{std::forward<T>(t)} }; { CommonType<T, U>{std::forward<U>(u)} }; };
å¤åè¦æ±
å¤åè¦æ±çå½¢å¼ä¸º
{ è¡¨è¾¾å¼ } noexcept(å¯é) è¿åç±»åè¦æ±(å¯é) ;
|
|||||||||
| è¿åç±»åè¦æ± | - | -> ç±»å约æ
|
å¹¶æè¨è¯¥å ·å表达å¼çå项æ§è´¨ã以ä¸å顺åºè¿è¡æ¿æ¢åè¯ä¹çº¦ææ£æ¥ï¼
template<typename T> concept C2 = requires(T x) { {*x} -> std::convertible_to<typename T::inner>; // è¡¨è¾¾å¼ *x å¿ é¡»åæ³ // å¹¶ä¸ ç±»å T::inner å¿ é¡»åæ³ // å¹¶ä¸ *x çç»æå¿ é¡»å¯ä»¥è½¬æ¢ä¸º T::inner {x + 1} -> std::same_as<int>; // è¡¨è¾¾å¼ x + 1 å¿ é¡»åæ³ // å¹¶ä¸ std::Same<decltype((x + 1)), int> å¿ é¡»è¢«æ»¡è¶³ // 亦å³ï¼(x + 1) å¿ é¡»ä¸º int ç±»åç纯å³å¼ {x * 1} -> std::convertible_to<T>; // è¡¨è¾¾å¼ x * 1 å¿ é¡»åæ³ // å¹¶ä¸å ¶ç»æå¿ é¡»å¯ä»¥è½¬æ¢ä¸º T };
åµå¥è¦æ±
åµå¥è¦æ±çå½¢å¼ä¸º
requires 约æè¡¨è¾¾å¼ ;
|
|||||||||
å®å¯ç¨äºä»¥å±é¨å½¢åæ¥æå®é¢å¤ç约æã约æè¡¨è¾¾å¼ å¿ é¡»è¢«ææ¿æ¢ç模æ¿å®åï¼è¥åå¨ï¼ææ»¡è¶³ãå¨åµå¥è¦æ±ä¸è¿è¡æ¨¡æ¿å®åçæ¿æ¢æå¯¼è´çå¨ çº¦æè¡¨è¾¾å¼ ä¸çæ¿æ¢ï¼ä» è¿è¡å°è¶³ä»¥ç¡®å® 约æè¡¨è¾¾å¼ æ¯å¦å¾å°æ»¡è¶³æéçç¨åº¦ã
template <class T> concept Semiregular = DefaultConstructible<T> && CopyConstructible<T> && Destructible<T> && CopyAssignable<T> && requires(T a, size_t n) { requires Same<T*, decltype(&a)>; // åµå¥ï¼âSame<...> æ±å¼ä¸º trueâ { a.~T() } noexcept; // å¤åï¼"a.~T()" æ¯ä¸æåºçåæ³è¡¨è¾¾å¼ requires Same<T*, decltype(new T)>; // åµå¥ï¼âSame<...> æ±å¼ä¸º trueâ requires Same<T*, decltype(new T[n])>; // åµå¥ { delete new T }; // å¤å { delete new T[n] }; // å¤å };
约æçé¨åæåº
å¨ä»»ä½è¿ä¸æ¥åæä¹åï¼å¯¹å个约æè¿è¡è§èåï¼å¯¹æ¯ä¸ªå ·åæ¦å¿µç主ä½åæ¯ä¸ª requires 表达å¼è¿è¡æ¿æ¢ï¼ç´å°å©ä¸åå约æçåå䏿åçåºå为æ¢ã
è¥æ ¹æ®çº¦æ P å约æ Q ä¸çååå约æçå䏿§å¯ä»¥è¯æ P è´å« Qï¼åç§° P å½å
¥ï¼subsumeï¼ Qãï¼å¹¶è¿è¡ç±»åå表达å¼ççä»·æ§åæï¼N > 0 å¹¶ä¸å½å
¥ N >= 0ï¼ã
å
·ä½æ¥è¯´ï¼é¦å
è½¬æ¢ P 为æåèå¼å¹¶è½¬æ¢ Q 为ååèå¼ãå½ä¸ä»
å½ä»¥ä¸æ
åµä¸ P å½å
¥ Qï¼
-
Pçæåèå¼ä¸çæ¯ä¸ªæååå¥é½å½å ¥Qçååèå¼ä¸çæ¯ä¸ªåååå¥ï¼å ¶ä¸ - å½ä¸ä»
彿ååå¥ä¸åå¨åå约æ
Uèåååå¥ä¸åå¨åå约æVï¼ä½¿å¾Uå½å ¥Væ¶ï¼æååå¥å½å ¥åååå¥ï¼ - å½ä¸ä»
å½ä½¿ç¨ä¸ææè¿°çè§åå¤å®ä¸ºçåæ¶ï¼ç§°åå约æ
Aå½å ¥åå约æBã
å½å ¥å ³ç³»å®ä¹äºçº¦æçé¨åæåºï¼ç¨äºç¡®å®ï¼
- éè½½å³è®®ä¸é模æ¿å½æ°çæä½³å¯è¡åé
- éè½½éä¸ç鿍¡æ¿å½æ°çå°å
- æ¨¡æ¿æ¨¡æ¿å®åçæä½³å¹é
- 类模æ¿ç¹åçé¨åæåº
- 彿°æ¨¡æ¿çé¨åæåº
| æ¬èæªå®æ åå ï¼ä»ä¸è¿°å 容添å å°æ¤çåé¾ |
è¥å£°æ D1 å D2 åå约æï¼ä¸ D1 å
³èç约æå½å
¥ D2 å
³èç约æï¼ï¼æ D2 æ 约æï¼ï¼åç§° D1 ä¸ D2 ç¸æ¯è³å°ä¸æ ·å约æãè¥ D1 è³å°ä¸ D2 䏿 ·å约æï¼è D2 å¹¶éè³å°ä¸ D1 䏿 ·å约æï¼å D1 æ¯ D2 æ´å约æã
template<typename T> concept Decrementable = requires(T t) { --t; }; template<typename T> concept RevIterator = Decrementable<T> && requires(T t) { *t; };  // RevIterator å½å ¥ Decrementableï¼ä½éç¸å  template<Decrementable T> void f(T); // #1  template<RevIterator T> void f(T); // #2ï¼æ¯ #1 æ´å约æ  f(0); // int ä» æ»¡è¶³ Decrementableï¼éæ© #1 f((int*)0); // int* 满足两个约æï¼éæ© #2ï¼å ä¸ºå®æ´å约æ  template<class T> void g(T); // #3ï¼æ 约æï¼  template<Decrementable T> void g(T); // #4  g(true); // bool 䏿»¡è¶³ Decrementableï¼éæ© #3 g(0); // int 满足 Decrementableï¼éæ© #4ï¼å ä¸ºå®æ´å约æ  template<typename T> concept RevIterator2 = requires(T t) { --t; *t; };  template<Decrementable T> void h(T); // #5  template<RevIterator2 T> void h(T); // #6  h((int*)0); // æ§ä¹