考慮以下代碼:ios
#include <type_traits> #include <iostream> #include <vector> using namespace std; template <typename T, typename = void> struct RangeConcept : std::false_type {}; template <typename T> struct RangeConcept<T, std::void_t< decltype( std::declval<T >().begin() ), decltype( std::declval<T >().end() ) > > : std::true_type {}; template<typename Cont> void show( Cont c){ static_assert( RangeConcept< Cont >::value, "must be a range. means.. it has begin() and end()" ); }
int main() {
std::vector<int> vec{1,2,3,4,5}; show(vec);
}
這就是C++17帶來的void_t神器。寫個靜態斷言無比容易。手寫個Concept檢查也再也不是C++庫開發者的專利了。spa
配合SNINAE和enable_if ,以下:code
template<typename T> void show(T& t, typename std::enable_if< RangeConcept<T>::value >::type* = 0){ std::cout << "I am a Range" << std::endl; } template<typename T> void show(T& t, typename std::enable_if< std::is_integral<T>::value >::type* = 0){ std::cout << "I am a others" << std::endl; } int main(){ std::vector<int> vec; int x=10; show(vec); }
參考:http://en.cppreference.com/w/cpp/types/void_tblog
原理:using引入類型別名開發
#include <iostream> template<int N,int M> struct add{ static constexpr int result = N + M; }; template<int M> using add8 = add<8,M>; int main(){ std::cout << add8<2>::result; }
C++17起,支持了變長模板參數it
template<typename...Args> using void_t = void; int f(void_t<int,char>){} int f(void){} int main(){ f(); }
連接錯誤。緣由在於void_t<int,char>等價於void,所以重定義了兩次f();io