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, 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)...); }
template<class T> auto len (T const& t) -> decltype( (void)(t.size()), T::size_type() ) { return t.size(); }
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"; }
template<class T, typename std::enable_if< !std::is_trivially_destructible<T>{} && (std::is_class<T>{} || std::is_union<T>{}), bool>::type = true> void destroy(T* t) { std::cout << "destroying non-trivially destructible T\n"; t->~T(); }
template<class T, typename = std::enable_if_t<std::is_array<T>::value> > void destroy(T* t) // note: function signature is unmodified { for(std::size_t i = 0; i < std::extent<T>::value; ++i) { destroy((*t)[i]); } }
当有多个重载时,不推荐使用该方式,会在C++语义上出现冲突,宜使用方法三。
template <typename T, typename = void> struct iterator_trait : std::iterator_traits<T> {}; template <typename T> struct iterator_trait<T, std::void_t<typename T::container_type>> : std::iterator_traits<typename T::container_type::iterator> {};
template<typename STR> requires std::is_convertible_v<STR,std::string> Person(STR&& n) : name(std::forward<STR>(n)) { ... }
template<typename T> concept ConvertibleToString = std::is_convertible_v<T,std::string>; ... template<typename STR> requires ConvertibleToString<STR> Person(STR&& n) : name(std::forward<STR>(n)) { ... }
template<ConvertibleToString STR> Person(STR&& n) : name(std::forward<STR>(n)) { ... }