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++ è¯è¨ > SFINAE
SFINAE
âæ¿æ¢å¤±è´¥ä¸æ¯é误â (Substitution Failure Is Not An Error)
å¨å½æ°æ¨¡æ¿çéè½½å³è®®ä¸åºç¨æ¤è§åï¼å½å°æ¨¡æ¿å½¢åæ¿æ¢ä¸ºæ¾å¼æå®çç±»åææ¨å¯¼çç±»å失败æ¶ï¼ä»éè½½éä¸ä¸¢å¼è¿ä¸ªç¹åï¼èé导è´ç¼è¯å¤±è´¥ã
æ¤ç¹æ§è¢«ç¨äºæ¨¡æ¿å ç¼ç¨ã
è§£é
坹彿°æ¨¡æ¿å½¢åè¿è¡ä¸¤æ¬¡æ¿æ¢ï¼ç±æ¨¡æ¿å®åææ¿ä»£ï¼ï¼
- æ¾å¼æå®ç模æ¿å®å卿¨¡æ¿å®åæ¨å¯¼ä¹åæ¿æ¢
- æ¨å¯¼çå®ååä»é»è®¤é¡¹è·å¾çå®å卿¨¡æ¿å®åæ¨å¯¼ä¹åæ¿æ¢
æ¿æ¢åçäº
- 彿°ç±»åä¸ä½¿ç¨çææç±»åï¼å å«è¿åç±»ååææå½¢åçç±»åï¼
- å个模æ¿å½¢å声æä¸ä½¿ç¨çææç±»å
|
(C++11 èµ·) |
|
(C++20 èµ·) |
å½ä»»ä½æ¿æ¢ä½¿ç¨ææ¿æ¢çå®åååºèé æä»¥ä¸ç±»åæè¡¨è¾¾å¼éè¯æï¼å¹¶å¸¦æå¿ è¦çè¯æï¼æ¶ï¼å®æ¯ä¸æ¬¡æ¿æ¢å¤±è´¥ã
坿彿°ç±»åæå ¶æ¨¡æ¿å½¢åç±»åæå ¶ explicit 说æç¬¦ (C++20 èµ·)çç«å³è¯å¢ä¸çç±»åä¸è¡¨è¾¾å¼ä¸çå¤±è´¥æ¯ SFINAE é误ãè¥å¯¹æ¿æ¢åçç±»å/表达å¼çæ±å¼å¯¼è´å¯ä½ç¨ï¼ä¾å¦å®ä¾åææ¨¡æ¿ç¹åãçææéå¼å®ä¹çæå彿°çï¼åè¿äºå¯ä½ç¨ä¸çé误被å½å硬é误ãlambda 表达å¼ä¸è¢«å½ä½æ¯ç«å³è¯å¢çä¸é¨åã (C++20 èµ·)
| æ¬èæªå®æ åå ï¼è¿æå½±åçå°ç¤ºä¾ |
|
æ¿æ¢ä»¥è¯æ³åºè¿è¡ï¼å¹¶å¨éå°å¤±è´¥æ¶ç»æ¢ã template <typename A> struct B { typedef typename A::type type; };  template < class T, class = typename T::type, // è¥ T æ æå type å为 SFINAE 失败 class U = typename B<T>::type // è¥ T æ æå type å为硬é误 // ï¼C++14 èµ·ä¿è¯ä¸åºç°ï¼ > void foo (int); 妿å¤ä¸ªå£°æå ·æä¸åçè¯æ³é¡ºåºï¼ä¾å¦ï¼æä¸ªå½æ°æ¨¡æ¿å£°æä¸ºå ·æå°¾éè¿åç±»åï¼å®å¨æä¸ªå½¢åä¹åæ¿æ¢ï¼ç¶å被é声æä¸ºå ·æå¸¸è§è¿åç±»åï¼å®åå¨è¯¥å½¢åä¹åæ¿æ¢ï¼ï¼åç¨åºéè¯æï¼æ é¡»è¯æã |
(C++14 èµ·) |
ç±»å SFINAE
ä¸åç±»åéè¯¯æ¯ SFINAE é误ï¼
|
(C++11 èµ·) |
- è¯å¾å建 void çæ°ç»ï¼å¼ç¨çæ°ç»ï¼å½æ°çæ°ç»ï¼è´å¤§å°çæ°ç»ï¼éæ´å大å°çæ°ç»ï¼æè é¶å¤§å°çæ°ç»ã
template <int I> void div(char(*)[I % 2 == 0] = 0) { // å½ I ä¸ºå¶æ°æ¶éæ©è¿ä¸ªéè½½ } template <int I> void div(char(*)[I % 2 == 1] = 0) { // å½ I ä¸ºå¥æ°æ¶éæ©è¿ä¸ªéè½½ }
- è¯å¾å¨ä½ç¨åè§£æè¿ç®ç¬¦
::左侧使ç¨å¹¶éç±»æéæä¸¾çç±»å
template <class T> int f(typename T::B*); template <class T> int f(T); int i = f<int>(0); // 使ç¨ç¬¬äºéè½½
- è¯å¾ä½¿ç¨ç±»åçæåï¼å ¶ä¸
- ç±»åä¸å«æå®æå
- å¨è¦æ±ç±»åå¤ï¼æå®æå䏿¯ç±»å
- å¨è¦æ±æ¨¡æ¿å¤ï¼æå®æå䏿¯æ¨¡æ¿
- å¨è¦æ±éç±»åå¤ï¼æå®æå䏿¯éç±»å
template <int I> struct X { }; template <template <class T> class> struct Z { }; template <class T> void f(typename T::Y*){} template <class T> void g(X<T::N>*){} template <class T> void h(Z<T::template TT>*){} struct A {}; struct B { int Y; }; struct C { typedef int N; }; struct D { typedef int TT; }; struct B1 { typedef int Y; }; struct C1 { static const int N = 0; }; struct D1 { template <typename T> struct TT { }; }; int main() { // ä¸åå个æ 嵿¨å¯¼å¤±è´¥ï¼ f<A>(0); // ä¸å«æå Y f<B>(0); // B ç Y æå䏿¯ç±»å g<C>(0); // C ç N æå䏿¯éç±»å h<D>(0); // D ç TT æå䏿¯æ¨¡æ¿  // ä¸åå个æ 嵿¨å¯¼æåï¼ f<B1>(0); g<C1>(0); h<D1>(0); } // æªå®æï¼éè¦æ¼ç¤ºéè½½å³è®®ï¼èä¸åªæ¯å¤±è´¥
- è¯å¾å建æåå¼ç¨çæé
- è¯å¾åå»ºå° void çå¼ç¨
- è¯å¾å建æå T æåçæéï¼å ¶ä¸ T 䏿¯ç±»ç±»å
template<typename T> class is_class { typedef char yes[1]; typedef char no [2]; template<typename C> static yes& test(int C::*); // è¥ C æ¯ç±»ç±»ååå¾å°éæ© template<typename C> static no& test(...); // å¦åéæ©å® public: static bool const value = sizeof(test<T>(0)) == sizeof(yes); };
- è¯å¾å°éæ³ç±»åç»äºéç±»åæ¨¡æ¿å½¢å
template <class T, T> struct S {}; template <class T> int f(S<T, T()>*); struct X {}; int i0 = f<X>(0); // æªå®æï¼éè¦æ¼ç¤ºéè½½å³è®®ï¼èéä» æ¯å¤±è´¥
- è¯å¾å¨ä»¥ä¸è¯å¢ä¸è¿è¡éæ³è½¬æ¢
- 模æ¿å®å表达å¼
- 彿°å£°æä¸ä½¿ç¨ç表达å¼
template <class T, T*> int f(int); int i2 = f<int,1>(0); // ä¸è½å° 1 转æ¢ä¸º int* // æªå®æï¼éè¦æ¼ç¤ºéè½½å³è®®ï¼èéä» æ¯å¤±è´¥
- è¯å¾å建形åç±»å为 void ç彿°ç±»å
- è¯å¾å建è¿åæ°ç»ç±»åæå½æ°ç±»åç彿°ç±»å
|
(C++11 å) |
|
(C++11 èµ·) |
è¡¨è¾¾å¼ SFINAE
|
ä¸å表达å¼éè¯¯æ¯ SFINAE é误
struct X {}; struct Y { Y(X){} }; // X å¯è½¬æ¢ä¸º Y  template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // éè½½ #1  X f(Y, Y); // éè½½ #2  X x1, x2; X x3 = f(x1, x2); // æ¨å¯¼å¨ #1 ä¸å¤±è´¥ï¼è¡¨è¾¾å¼ x1+x2 éè¯æï¼ // ä» #2 å¨éè½½éä¸ï¼å¹¶å¾å°è°ç¨ |
(C++11 èµ·) |
|
C++11 åï¼åªæç±»åä¸ä½¿ç¨ç常é表达å¼ï¼ä¾å¦æ°ç»è¾¹çï¼æè¦æ±è¢«å½å SFINAEï¼èé硬é误ï¼ã |
(C++11 å) |
åºæ¯æ
æ ååºç»ä»¶ std::enable_if å 许åå»ºæ¿æ¢å¤±è´¥ï¼ä»¥åºäºæä¸ªå¨ç¼è¯æ¶æ±å¼çæ¡ä»¶æ¥å¯ç¨æç¦ç¨ç¹å®çéè½½ã
æ ååºç»ä»¶ std::void_t æ¯å¦ä¸ä¸ªç®å SFINAE çåºç¨çå·¥å ·å 彿°ã
å¦å¤ï¼è®¸å¤ç±»åç¹æ§é½æ¯ç¨ SFINAE å®ç°çã
æ¿ä»£æ¹æ¡
åªè¦éç¨ï¼æ ç¾æ´¾åï¼static_assertï¼ä»¥åï¼å¦æå¯ç¨ï¼æ¦å¿µï¼é叏齿¯ç´æ¥ä½¿ç¨ SFINAE æ´åå好ã
示ä¾
ä¸ç§å¸¸è§ææ³ï¼æ¯å¨è¿åç±»åä¸ä½¿ç¨è¡¨è¾¾å¼ SFINAEï¼å ¶ä¸è¡¨è¾¾å¼ä½¿ç¨éå·è¿ç®ç¬¦ï¼å ¶å·¦åè¡¨è¾¾å¼æ¯ææ£éªçï¼è½¬åå° void 以确ä¿ä¸ä¼éæ©è¿åç±»åä¸çç¨æ·å®ä¹éå·è¿ç®ç¬¦ï¼ï¼èå³å表达å¼å ·æææå½æ°è¿åçç±»åã
#include <iostream>  // æ¤éè½½å§ç»å¨éè½½éä¸ // çç¥å·å½¢å对äºéè½½å³è®®å ·ææä½ç级 void test(...) { std::cout << "Catch-all overload called\n"; }  // è¥ C æ¯ç±»çå¼ç¨ç±»åä¸ F æ¯æå C çæå彿°çæé // åè¿ä¸ªé载被添å å°éè½½éï¼ template <class C, class F> auto test(C c, F f) -> decltype((void)(c.*f)(), void()) { std::cout << "Reference overload called\n"; }  // è¥ C æ¯ç±»çæéç±»åä¸ F æ¯æå C çæå彿°çæé // åè¿ä¸ªé载被添å å°éè½½éï¼ template <class C, class F> auto test(C c, F f) -> decltype((void)((c->*f)()), void()) { std::cout << "Pointer overload called\n"; }  struct X { void f() {} };  int main(){ X x; test( x, &X::f); test(&x, &X::f); test(42, 1337); }
è¾åºï¼
Reference overload called Pointer overload called Catch-all overload called