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;
}
or
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_void
is_floating_point Floating point type ( Non pointer )
is_array
is_pointer Pointer type ( Include function pointers , Does not include member function pointers )
is_enum
is_union Is it not union Of class/struct
is_class
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
#include<iostream>
#include<type_traits>
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
add_const
remove_reference
add_lvalue_reference
add_rvalue_reference
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*
Create()
{
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;
count<<typeid(max_size_t).name()<<endl;
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
#include<type_traits>
class A
{
A() = delete;
public:
int operator()(int i)
{
return i;
}
};
int main ()
{
decltype(A()(0)) i =4;
cout<<i<<endl;
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
example1:
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
example2:
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()
{
Func(1);
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)
{
cout<<typeid(T).name()<<endl;
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
{
cout<<typeid(T).name()<<endl;
}
typename std::enable_if<std::is_same<T, std::string>::value>::type foo1(T& t)
{
cout<<typeid(T).name()<<endl;
}
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; }
Technology
Daily Recommendation