1.type_traits- Type extraction

 (1)type_traits It can be eliminated to some extent switch-case perhaps if-else sentence , Reduce the complexity of the program

(2) The correct type can be checked at compile time

1.1 Basic type_traits

Defining compile time constants

  struct GetLeftSize


   static const int value =1;



 struct GetLeftSize


   enum { value = 1};


stay c++11 Define compile time constants in , You don't have to define it yourself static const int or enum type , Just from the std::integral_constant derive :

template<typename Type>

struct GetLeftSize : std::integral_constant<int, 1>



It can be done through GetLeftSize::value To get a constant 1, look down integral_constant Packaging :

template<class T, T v>

struct integral_constant


 static const T value = v;

 typedef T value_type;

 typedef integral_constant<T, v> type;

 operator vaue_type() {return value;}


and true_type and false_type yes integtal_constant An example of :

typedef integral_constant<bool, true> true_type;

typedef integral_constant<bool, false> false_type;

std::true_type and std::false_type The true and false type

1.2 Typological type_traits

template<class T>

struct is_integral;

inspect T type : bool char char16_t char32_t wchar_t short int
long longlong, One of them is back true.std::is_integral::value by true


is_floating_point Floating point type ( Non pointer )


is_pointer Pointer type ( Include function pointers , Does not include member function pointers )


is_union Is it not union Of class/struct


is_function Is it a function type

is_reference Is it a reference type ( Either the left or the right will do )

is_arithmetic Is it integer and floating point

is_fundamental Is it an integer , floating-point ,void,nullptr_t

is_object Is it an object type ( Not a function It's not a reference no void)

is_member_pointer Is it a member function pointer type

is_polymorphic virtual function

is_abstract abstract class

is_signed Signed type

is_unsigned Unsigned type

is_const by const Types of modifications

adopt std::is_xxx::value To determine whether the conditions are met

std::is_const<const int&>::value == true;

std::is_const<const int* >::value == false;

1.3 traits To judge the relationship between the two types

template<class T, class U>

struct is_same; Judge whether the two types are the same

template<class Base, class Derived>

struct is_base_of; // judge Base Is it Derived Base class of

template<class From, class To>

struct is_convertible; Determine whether the former type can be converted to the latter type



class A {};

class B : public A{};

class C{};

int mian()


 bool b2a = std::is_convertible<B*, A*>::value; // true

 bool a2b = std::is_convertible<A*, B*>::value; // false Cannot switch down



3.type_traits of Conversion of type

template<class T>

struct remove_const; remove const

The following is omitted template<class T> struct





remove_extent // Remove the dimension at the top of the array

remove_all_extent // Remove all dimensions of the array

remove_pointer Remove pointer

add_pointer Add pointer

decay remove cv Or add a pointer

common_type Get public type

Get the converted type through the :

std::xx<>::type To get the , wrong ::value

When an object is created from a template parameter class , Be careful to remove references :

template<typename T>

typename std::remove_reference<T>::type* Create()


   typedef typename std::remove_reference<T>::type U;

   return new U();


In the example above , Return value and function typename Is because of the nested dependent type of the template , Take a good look at the template foundation ! Ha ha ha ~~~~

The template parameter type may be a reference type , When the object is created , The original type is required , Cannot use reference type , So you need to remove the possible references

remove cv reference type ( What the hell , Never seen it , To satisfy the sense of honor , Plus it )

template<typename T>

T* Create()

  return new T();


int* p = Create<const volatile int&>();

Compilation failed ; Need to remove references and cv To get the original type int

template<typename T>

typename std::remove_cv<typename std::remove_reference<T>::type>::type*


  typedef typename std::remove_cv<typename
std::remove_reference<T>::type>::type U;

  return new U();


The code is long , use decay Instead of removing references and cv( Hemp egg , What the hell? , I'm not just talking about it decay Where can I go cv, How can we get more citations ,~~~):

template<typename T>

typename std::decay<T>::type* Create()


 typedef typename std::decay<T>::type U;

 return new U;


cv : const volatile

decay It's more than that , It can also be used for arrays and functions :

Remove first T The type of the reference , Get the type U,U Defined as remove_reference<T>::type

If is_array<U>::value by true, Modification type type by remove_extent<U>::type*;

Otherwise, if is_function<U>::value by true, The modification type is add_pointer<U>::type

Otherwise, the modification type is remove_cv<U>::type, Where to go const or volatile

( The above rules are really disgusting , that SB Defined !!)

int&& ---int

const int& -- int

int[2] -- int*

int(int) -- int(*)(int)

Functions can be saved by changing them into function pointers ( But what the hell does it mean when a function becomes a function pointer ? It's similar int(int) become int(*)(int) Do you ?)

using FnType = typename std::decay<F>::type Implement the definition of function pointer type

1.2 traits -- Select according to conditions

std::conditional At compile time, select one of the two types based on a judgment :

template<bool B, class T, class F>

struct conditional;

If B by true, be conditional::type by T, Otherwise F

Compare the two types with the larger output :

 typedef std::conditional<(sizeof(long long) > sizeof(long double)), long
long, long double>::type max_size_t;


1.3 traits-- Gets the callable object return type

template<typename F, typename Arg>

?? Func(F f, Arg arg)


  return f(r);


The type of return cannot be determined directly ; It can be done through decltype To infer :

template<typename F, typename Arg>

decltype((*(F*)0)((*(Arg*)0))) Func(F f, Arg arg)

  return f(arg);


The front is so hard to understand ? forget it , Let's look at the back

template<typename F, typename Arg>

auto Func(F f, Arg arg)->decltype(f(arg))


  return f(arg);


The above code has no parameters , It can't pass decltype To derive the type


class A

   A() = delete;


  int operator()(int i)


    return i;



int main ()


  decltype(A()(0)) i =4;


  return 0;


The above code will report an error , because A There is no default constructor ; For types that do not have a default constructor , If you want to deduce the return type of its member function , Need help std::declval

decltype(std::declval<A>()(std::declval<int>())) i =4;

std::declval Can get any type of temporary value , Whether it has a default constructor or not , therefore , It can be done through declval<A>() To get A Temporary value of ;

notes :declval The temporary value reference obtained cannot be used for evaluation , therefore , Need to use decltype To infer the final return type

c++11 Another one is provided trait function , Used to get a callable object ,std::result_of, This is really hanging !!!!!!!!!!!!!

std::result_of<A(int)>::type i = 4;

actually ,std::result_of<A(int)>::type It's actually equivalent to
decltype(std::declval<A>()(std::declval<int>()))  This isn't going to work , It's hard to input !!!

std::result_of The prototype is as follows :

tempalte<class F, class...ArgTypes>

class result_of<F(ArgTypes...)>;

std::result_of<Fn(ArgTypes...)> requirement Fn Is a callable object , Cannot be a function type , The function type is not a callable object .

typedef std::result_of<decltype(fn)(int)>::type A; // This approach is wrong , This is a function, not a callable object

Here's the definition of the function object :

 1. Function pointer

2. have operator() Class object of member function ( functor )

3. A class object that can be converted to a function pointer

4. Class member ( function ) Pointer

I won't give you an example , You can't read it anyway , Ha ha ha ~~~~~~~

result_of The example begins , Zhennima is very powerful ,,,,, However, it is rare that a class has no constructor , So is it used decltype Better , There is no need to convert to a callable object


int fn(int) { return int(); }  function

If you want to use std::result_of, First, convert the function to a callable object

typedef std::result_of<decltype(fn)& (int)> ::type A;  // What the hell is this ???

typedef std::result_of<decltype(fn)* (int)>::type B;   // I can't understand this ????

typedef std::result_of<typename std::decay<decltype(fn)>::type(int)> ::type C;

static_assert(std::is_same<A, B>::value, "not equal"); true

static_assert(std::is_same<A, C>::value, "not equal"); true

static_assert(std::is_same<B, C>::value, "not equal"); true


template<typename Fn>

auto GroupBy(const vector<Person>& vt, const Fn& keySelector)-> multimap(
decltype(keySelector((Person& ) nullptr)), Person>


      typedef decltype(keySelector(*(Person*) nullptr)) key_type;

     multimap<key_type, Person> map;

      std::for_each(vt.begin(), vt.end(), [&](const Person& person)


       map.insert(make_pair(keySelector(person), person));


    return map;


You can see that the key value is Fn As a function ,Person Object as an input parameter to get the .

however decltype(keySelector(*(Person*) nullptr)) key_type It's hard to understand ??????ri

use result_of To replace

template<typename Fn>

multimap<typename std::result_of<Fn(Person)>::type, Person>

GroupBy(const vector<Person>& vt, Fn&& keySelector)


  typedef std::result_of<Fn(Person)>:: type key_type; //
Fn(Person) There are types in both , Is it a parameter or both ????

  multimap<key_type, Person> map;

  std::for_each(vt.begin(), vt.end(), [&] (const Person& person)


  map.insert(make_pair(keySelector(person), person));


return map;


1.4 traits-- Disable or enable depending on conditions

Matching overloaded functions :

 template<typename T>

void Fuc(T*){ }

template<typename T>

void Fun(T){}

int main()


  return 0;


Will match the second overloaded function

template<bool B, class T = void> 

struct enable_if;

In judging conditions B by true Time ,enable_if To be effective , Otherwise, the compilation fails

template<class T>

typename std::enable_if<std::is_arithmetic<T>::value, T>::type foo(T t)


  return t;


auto r = foo(1);

auto r1 = foo(1.2);

auto r2 = foo("tess"); // Compilation error        

std::enable_if Not only can it act on the return value , It can also act on template definitions , class template specializations , Qualification of input parameter type

// Determine whether the second input parameter type is integral type ( I feel that there is something wrong with this sentence , Because of judgment T Is it an integer ,T It's also the first parameter type ? Do you think so ?)

template<calss T>

T foo2(T t, typename std::enable_if<std::is_integral<T>::value, int>::type =
0) // The default value is 0


  return t;


foo2(1,2); sure

foo2(1," "); Second parameter error

// For template parameters T It's limited ,T Only for integral type

template<class T, class = typename
std::enable_if<std::is_integral<T>::value>::type >

T foo3(T t)


  return t;


template<class T, class Enable = void>

class A;

// template specialization , The template parameters are limited , Template parameters can only be floating-point

template<class T>

class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type>{};

A<double> a;

A<int> a; // Compilation error , Template parameter should be floating point

requirement : For input parameters arithmetic Return of type 0 , wrong arithmetic Return of type 1;

template<class T>

typename enable_if<std::is_arithmetic<T>::value, int> ::type foo(T t)


  cout<<t <<endl;

  return 0;


template<class T>

typename enable_if<!std::is_arithmetic<T>::value, int>::type foo(T& t)



 return 1;


std::enable_if The second parameter of is the default template parameter void type , Therefore, when the function does not return a value , The following template parameters can be omitted

typename std::enable_if<std::is_arithmetic<T>::value>::type fool(T t) 
// The return value is void, The previous is to check whether the type meets the criteria




typename std::enable_if<std::is_same<T, std::string>::value>::type foo1(T& t)




You can see std::enable_if The powerful overload mechanism of , It can be overloaded even if the return value is the same ,(NIMA When I'm blind , Isn't the input parameter type different ? Does it affect the effect of quotation ?????)

Here's a piece of code :

template<typename T>

string ToString(T t)


  if(typeid(T) == typeid(int) || typeid(T) == typeid(double) || typeid(T) ==
typeid(float) )


  std::string stream ss;

  ss<<value;  // Don't ask me , I can't understand this sentence ??????????????

 return ss.str();

else if(typeid(T) == typeid(string))


 return t;



use enable_if To replace :

template<class T>

typename std::enable_if<std::is_arithmetic<T>::value, string>::type

  ToString(T& t) { return std::to_string(t); }

tempalte<class T>

typename std::enable_if<std::is_same<T, std::string>::value, string>::type

 ToString(T& t) { return t; }

©2019-2020 Toolsou All rights reserved,
QT Delete directory and file Java aggregate ------LinkedHashMap Underlying principle I've been drinking soft water for three years ? What is the use of soft water and water softener Java Xiao Ming A+B About wechat payment body( Product description ) Problems encountered Digital rolling lottery program 3 species Python data structure ,13 Creation methods , This is the conclusion , Great ! Huawei Mate 40 Pro+ 5G exposure : Leica film lens , Ceramic body What's the difference in server prices ? Operators Website visitors' mobile phone number capture