获取T的原始类型,我们通过std::remove_reference移除引用,需要获取智能指针指向的对象时需要对原始类型U添加左值引用。
#include <iostream>
#include <type_traits>
#include <memory>
template <typename T>
struct Construct
{
typedef typename std::remove_reference<T>::type U; // 移除可能的引用
Construct():m_ptr(new U)
{}
typename std::add_lvalue_reference<U>::type // 添加左值引用
Get() const
{
return *m_ptr.get();
}
private:
std::unique_ptr<U> m_ptr;
};
main()
{
Construct<int> c;
int a = c.Get();
std::cout << a << std::endl;
}
std::decay的用法 基本类型 typedef decay<int>::type A; // A is int typedef decay<int &>::type B; // B is int typedef decay<int &&>::type C; // C is int typedef decay<const int &>::type D; // D is int typedef decay<int[2]>::type E; // E is int * typedef decay<int(int)>::type F; // F is int(*)(int)
非基本类型
class MyClass {};
typedef decay<MyClass>::type A; // A is MyClass
typedef decay<MyClass &>::type B; // B is MyClass
typedef decay<MyClass &&>::type C; // C is MyClass
typedef decay<const MyClass &>::type D; // D is MyClass
typedef decay<MyClass[2]>::type E; // E is MyClass *
typedef decay<MyClass *>::type F; // E is MyClass *
typedef decay<MyClass *[2]>::type G; // G is MyClass **
typedef decay<MyClass **>::type H; // H is MyClass **
declval的用法
// declval example
#include <utility> // std::declval
#include <iostream> // std::cout
struct A { // abstract class
virtual int value() = 0;
};
class B : public A { // class with specific constructor
int val_;
public:
B(int i,int j):val_(i*j){}
int value() {return val_;}
};
int main() {
decltype(std::declval<A>().value()) a; // int a
decltype(std::declval<B>().value()) b; // int b
decltype(B(0,0).value()) c; // same as above (known constructor)
a = b = B(10,2).value();
std::cout << a << '\n';
return 0;
}
#include <iostream>
#include <type_traits>
using std::cout;
using std::endl;
struct A
{
};
struct B : A
{
};
int FTest(std::string strNum)
{
return atoi(strNum.c_str());
}
template <typename F, typename Arg>
auto Func(F f, Arg arg)->decltype(f(arg))
{
return f(arg);
}
class C
{
C() = delete;
public:
int operator()(int i)
{
return i;
}
std::string StrValue(std::string str)
{
return str;
}
};
int fn(int) { return int(); }
int main() {
typedef std::integral_constant<int, 1> one_t;
// 1.简单的type_traits
cout << "one_t::value: " << one_t::value << endl;
cout << "one_t::type::value: " << one_t::type::value << endl;
// 2.类型判断的traits
cout << std::is_integral<int>::value << endl; // 判断是否为基本类型
cout << std::is_pointer<int*>::value << endl; // 判断是否为指针
// 3.判断两个类型关系的traits
cout << std::is_base_of<A, B>::value << endl; // 判断前边的模板参数是否为后边的基类
cout << std::is_convertible<B, A>::value << endl; // 判断前边的模板参数能否转换为后边的
// 4.类型转换的traits
cout << std::is_same<int, std::remove_pointer<int*>>::value << endl;
cout << std::is_same<int[2][3], std::remove_extent<int[][2][3]>>::value << endl; // 移除顶层维度
// 取公共类型
typedef std::common_type<unsigned char, int, short>::type NumbericType;
cout << std::is_same<int, NumbericType>::value << endl;
// 根据条件选择的traits
typedef std::conditional<std::is_integral<int>::value, int, long>::type TypeName; // int,否则long
cout << typeid(TypeName).name() << endl; // 输出int
// 获取可调用对象返回类型的traits
auto nNum = Func(FTest, "256"); // 通过decltype来获取返回类型
cout << nNum << endl;
// 但是如果某个类型没有模板参数时,就不能通过decltype来获取类型了
// 这种没有默认构造函数的类型,需要借助declval来推导其成员函数的返回类型
decltype(std::declval<C>()(std::declval<int>())) i = 4;
decltype(std::declval<C>().StrValue(std::declval<std::string>())) str = "";
// 为了简洁可以使用另一个traits std::result_of
std::result_of<C(int)>::type i2 = 4; // 等价于上边的 ... i = 4;
typedef int(*fn_ptr)(int);
typedef int(&fn_ref)(int);
struct fn_class{
int operator()(int i) { return i; };
};
std::result_of<decltype(fn)& (int)> Atype; // int
std::result_of<fn_ptr(int)>::type Btype; // int
std::result_of<fn_ref(int)>::type Ctype; // int
std::result_of<fn_class(int)>::type Dtype; // int
getchar();
}
使用type_traits来在编译期获取参数最大值:
template <size_t arg, size_t... rest>
struct MaxInteger;
template <size_t arg>
struct MaxInteger<arg>:std::integral_constant<size_t ,arg>{};
template <size_t arg1, size_t arg2, size_t... rest>
struct MaxInteger<arg1, arg2, rest...> :std::integral_constant<size_t, arg1
>= arg2 ? MaxInteger<arg1, rest...>::value : MaxInteger<arg2, rest...>::value>
{
// 例子:8 5 1 9 7 6 3 4 -> 8 1 9 7 6 3 4 -> 8 9 7 6 3 4 -> ... -> 8
// 相当于冒泡排序,只剩一个参数时走递归停止模板函数
};