type_traits学习

 

 

获取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
    // 相当于冒泡排序,只剩一个参数时走递归停止模板函数
};

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值