C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- std::result_of, std::invoke_result
- std::integral_constant
- std::is_constant_evaluated
- std::max_align_t
- offsetof
- NULL
- std::bad_typeid
- std::bad_cast
- std::numeric_limits
- std::type_info
- std::ptrdiff_t
- std::byte
- std::conjunction
- std::disjunction
- std::negation
- std::is_swappable_with, std::is_swappable, std::is_nothrow_swappable_with, std::is_nothrow_swappable
- std::is_invocable, std::is_invocable_r, std::is_nothrow_invocable, std::is_nothrow_invocable_r
- std::is_aggregate
- std::has_unique_object_representations
- std::endian
- std::remove_cvref
- std::type_index
- C æ°å¼æéæ¥å£
- å®å®½æ´æ°ç±»å (C++11 èµ·)
- std::is_bounded_array
- std::is_unbounded_array
- std::size_t
- std::nullptr_t
- std::is_integral
- std::rank
- std::is_void
- std::is_null_pointer
- std::is_array
- std::is_pointer
- std::is_enum
- std::is_union
- std::is_class
- std::is_function
- std::is_object
- std::is_scalar
- std::is_compound
- std::is_floating_point
- std::is_fundamental
- std::is_arithmetic
- std::is_reference
- std::is_lvalue_reference
- std::is_rvalue_reference
- std::is_member_pointer
- std::is_member_object_pointer
- std::is_member_function_pointer
- std::is_const
- std::is_volatile
- std::is_empty
- std::is_polymorphic
- std::is_final
- std::is_abstract
- std::is_trivial
- std::is_trivially_copyable
- std::is_standard_layout
- std::is_literal_type
- std::is_pod
- std::is_signed
- std::is_unsigned
- std::is_constructible, std::is_trivially_constructible, std::is_nothrow_constructible
- std::is_default_constructible, std::is_trivially_default_constructible, std::is_nothrow_default_constructible
- std::is_copy_constructible, std::is_trivially_copy_constructible, std::is_nothrow_copy_constructible
- std::is_move_constructible, std::is_trivially_move_constructible, std::is_nothrow_move_constructible
- std::is_assignable, std::is_trivially_assignable, std::is_nothrow_assignable
- std::is_copy_assignable, std::is_trivially_copy_assignable, std::is_nothrow_copy_assignable
- std::is_move_assignable, std::is_trivially_move_assignable, std::is_nothrow_move_assignable
- std::is_destructible, std::is_trivially_destructible, std::is_nothrow_destructible
- std::has_virtual_destructor
- std::is_same
- std::is_base_of
- std::is_convertible, std::is_nothrow_convertible
- std::is_layout_compatible
- std::is_pointer_interconvertible_base_of
- std::is_pointer_interconvertible_with_class
- std::is_corresponding_member
- std::alignment_of
- std::extent
- std::remove_cv, std::remove_const, std::remove_volatile
- std::add_cv, std::add_const, std::add_volatile
- std::make_signed
- std::make_unsigned
- std::remove_reference
- std::add_lvalue_reference, std::add_rvalue_reference
- std::remove_pointer
- std::add_pointer
- std::remove_extent
- std::remove_all_extents
- std::aligned_storage
- std::aligned_union
- std::decay
- std::enable_if
- std::void_t
- std::conditional
- std::common_type
- std::common_reference
- std::underlying_type
- std::type_identity
- 注é
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼ > std::enable_if
std::enable_if
è¥ B 为 true ï¼å std::enable_if æ¥æçåäº T çå
¬å¼æå typedef type ï¼å¦åï¼æ 该æå typedef ã
æ¤å
彿°æ¯æ´»ç¨ SFINAE ï¼åºäºç±»åç¹æ§æ¡ä»¶æ§å°ä»éè½½å³è®®ç§»é¤å½æ°ï¼å¹¶å¯¹ä¸åç±»åç¹æ§æä¾å离ç彿°éè½½ä¸ç¹åçä¾¿å©æ¹æ³ã std::enable_if å¯ç¨ä½é¢å¤ç彿°åæ°ï¼ä¸å¯åºç¨äºè¿ç®ç¬¦éè½½ï¼ãè¿åç±»åï¼ä¸å¯åºç¨äºæé 彿°ä¸ææå½æ°ï¼ï¼æç±»æ¨¡æ¿æå½æ°æ¨¡æ¿å½¢åã
æ·»å enable_if çç¹åçç¨åºè¡ä¸ºæªå®ä¹ã
æåç±»å
| Â | |
| ç±»å | å®ä¹ |
type
|
ä¾èµ B çå¼ï¼ä¸º T ææ æ¤æå
|
è¾ å©ç±»å
| template< bool B, class T = void > using enable_if_t = typename enable_if<B,T>::type; |
(C++14 èµ·) | |
å¯è½çå®ç°
template<bool B, class T = void> struct enable_if {}; Â template<class T> struct enable_if<true, T> { typedef T type; }; |
注解
常è§é误æ¯å£°æäºä¸ªå½æ°æ¨¡æ¿ï¼èå®ä»¬ä» äºå ¶é»è®¤æ¨¡æ¿å®åç¸å¼ãè¿æ¯æ æçï¼å 为è¿äºå½æ°å£°æè¢«å½ååä¸å½æ°æ¨¡æ¿çå声æï¼é»è®¤æ¨¡æ¿å®åä¸ä¸ºå½æ°æ¨¡æ¿çä»·æèèï¼ã
/* WRONG */ Â struct T { enum { int_t,float_t } m_type; template <typename Integer, typename = std::enable_if_t<std::is_integral_v<Integer>> > T(Integer) : m_type(int_t) {} Â template <typename Floating, typename = std::enable_if_t<std::is_floating_point_v<Floating>e> > T(Floating) : m_type(float_t) {} // error: cannot overload }; Â /* RIGHT */ Â struct T { enum { int_t,float_t } m_type; template <typename Integer, std::enable_if_t<std::is_integral_v<Integer>, int> = 0 > T(Integer) : m_type(int_t) {} Â template <typename Floating, std::enable_if_t<std::is_floating_point_v<Floating>, int> = 0 > T(Floating) : m_type(float_t) {} // OK };
äºå½å空é´å½æ°æ¨¡æ¿ä½ç¨åçæ¨¡æ¿éç±»åå½¢åä¸ä½¿ç¨ enable_if æ¶éçæãæäº ABI è§èï¼å¦ Itanium ABI ï¼ä¸äºéæ´ä¸å
å«éç±»åæ¨¡æ¿å½¢åçå®ä¾åä¾èµé¨åãè¿è¡¨ç¤ºå¯è½ä»¥ç¸åéæ´åå½çº³äºä¸ªç¸å¼ç彿°æ¨¡æ¿ç¹åï¼å¹¶ä¸é误å°ç¸äºé¾æ¥ãä¾å¦ï¼
// 第ä¸ä¸ªç¿»è¯åå  struct X { enum { value1 = true, value2 = true }; };  template<class T, std::enable_if_t<T::value1, int> = 0> void func() {} // #1  template void func<X>(); // #2  // 第äºä¸ªç¿»è¯åå  struct X { enum { value1 = true, value2 = true }; };  template<class T, std::enable_if_t<T::value2, int> = 0> void func() {} // #3  template void func<X>(); //#4
彿°æ¨¡æ¿ #1 ä¸ #3 æ¥æä¸åç¾åï¼ä¸ä¸ºä¸åçæ¨¡æ¿ãä¸è¿ #2 ä¸ #4 尽管æ¯ä¸å彿°æ¨¡æ¿çå®ä¾åï¼å´äº Itanium C++ ABI æ¥æç¸åçéæ´åï¼ _Z4funcI1XLi0EEvv ï¼ï¼è¿è¡¨ç¤ºé¾æ¥å¨ä¼é误å°è®¤ä¸ºå®ä»¬æ¯åä¸å®ä½ã
示ä¾
#include <type_traits> #include <new> #include <iostream> #include <string>  namespace detail {  void* voidify(const volatile void* ptr) noexcept { return const_cast<void*>(ptr); }  }  // #1 ï¼ç»ç±è¿åç±»åå¯ç¨ template<class T> typename std::enable_if<std::is_trivially_default_constructible<T>::value>::type construct(T*) { std::cout << "default constructing trivially default constructible T\n"; }  // åä¸ template<class T> typename std::enable_if<!std::is_trivially_default_constructible<T>::value>::type construct(T* p) { std::cout << "default constructing non-trivially default constructible T\n"; ::new(detail::voidify(p)) T; }  // #2 template<class T, class... Args> std::enable_if_t<std::is_constructible<T, Args&&...>::value> // Using helper type construct(T* p, Args&&... args) { std::cout << "constructing T with operation\n"; ::new(detail::voidify(p)) T(static_cast<Args&&>(args)...); }  // #3 ï¼ç»ç±åæ°å¯ç¨ template<class T> void destroy( T*, typename std::enable_if< std::is_trivially_destructible<T>::value >::type* = 0 ){ std::cout << "destroying trivially destructible T\n"; }  // #4 ï¼ç»ç±éç±»åæ¨¡æ¿å½¢åå¯ç¨ template<class T, typename std::enable_if< !std::is_trivially_destructible<T>{} && (std::is_class<T>{} || std::is_union<T>{}), int>::type = 0> void destroy(T* t) { std::cout << "destroying non-trivially destructible T\n"; t->~T(); }  // #5 ï¼ç»ç±ç±»å模æ¿å½¢åå¯ç¨ template<class T, typename = std::enable_if_t<std::is_array<T>::value> > void destroy(T* t) // 注ï¼ä¸ä¿®æ¹å½æ°ç¾å { for(std::size_t i = 0; i < std::extent<T>::value; ++i) { destroy((*t)[i]); } } /* template<class T, typename = std::enable_if_t<std::is_void<T>::value> > void destroy(T* t){} // é误ï¼å½æ°ç¾åä¸ #5 ç¸å */  // ç»ç±æ¨¡æ¿å½¢åå¯ç¨ A çåç¹å template<class T, class Enable = void> class A {}; // åçæ¨¡æ¿  template<class T> class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> { }; // æµ®ç¹ç±»åçç¹å  int main() { std::aligned_union_t<0,int,std::string> u;  construct(reinterpret_cast<int*>(&u)); destroy(reinterpret_cast<int*>(&u));  construct(reinterpret_cast<std::string*>(&u),"Hello"); destroy(reinterpret_cast<std::string*>(&u));  A<int>{}; // OK ï¼å¹é åçæ¨¡æ¿ A<double>{}; // OK ï¼å¹é åç¹å+ }
è¾åºï¼
default constructing trivially default constructible T destroying trivially destructible T constructing T with operation destroying non-trivially destructible T
åé
| (C++17) |
void ååå«åæ¨¡æ¿ (å«å模æ¿) |