type_traits学习

 

 

获取T的原始类型,我们通过std::remove_reference移除引用,需要获取智能指针指向的对象时需要对原始类型U添加左值引用。 

#include 
#include 
#include 

template 
struct Construct
{
    typedef typename std::remove_reference::type U;  // 移除可能的引用
    Construct():m_ptr(new U)
    {}
    typename std::add_lvalue_reference::type // 添加左值引用
        Get() const
    {
        return *m_ptr.get();
    }
private:
    std::unique_ptr m_ptr;
};

main()
{
    Construct c;
    int a = c.Get();
    std::cout << a << std::endl;
}
 std::decay的用法
基本类型
typedef decay::type A; // A is int
typedef decay::type B; // B is int
typedef decay::type C; // C is int
typedef decay::type D; // D is int
typedef decay::type E; // E is int *
typedef decay::type F; // F is int(*)(int)

非基本类型
class MyClass {};

typedef decay::type A; // A is MyClass
typedef decay::type B; // B is MyClass
typedef decay::type C; // C is MyClass
typedef decay::type D; // D is MyClass
typedef decay::type E; // E is MyClass *
typedef decay::type F; // E is MyClass *
typedef decay::type G; // G is MyClass **
typedef decay::type H; // H is MyClass **

declval的用法

// declval example
#include       // std::declval
#include      // 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().value()) a;  // int a
  decltype(std::declval().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 
#include 

using std::cout;
using std::endl;

struct A
{
};

struct B : A
{
};

int FTest(std::string strNum)
{
    return atoi(strNum.c_str());
}

template 
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 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::value << endl;   // 判断是否为基本类型
    cout << std::is_pointer::value << endl;   // 判断是否为指针
    // 3.判断两个类型关系的traits
    cout << std::is_base_of::value << endl;  // 判断前边的模板参数是否为后边的基类
    cout << std::is_convertible::value << endl;  // 判断前边的模板参数能否转换为后边的
    // 4.类型转换的traits
    cout << std::is_same>::value << endl;
    cout << std::is_same>::value << endl;    // 移除顶层维度
    // 取公共类型
    typedef std::common_type::type NumbericType;
    cout << std::is_same::value << endl;
    // 根据条件选择的traits
    typedef std::conditional::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()(std::declval())) i = 4;
    decltype(std::declval().StrValue(std::declval())) str = "";
    // 为了简洁可以使用另一个traits std::result_of
    std::result_of::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 Atype;  // int
    std::result_of::type Btype;    // int
    std::result_of::type Ctype;    // int
    std::result_of::type Dtype;  // int
    getchar();
}

使用type_traits来在编译期获取参数最大值:


template 
struct MaxInteger;

template 
struct MaxInteger:std::integral_constant{};

template 
struct MaxInteger :std::integral_constant= arg2 ? MaxInteger::value : MaxInteger::value>
{
    // 例子:8 5 1 9 7 6 3 4 -> 8 1 9 7 6 3 4 -> 8 9 7 6 3 4 -> ... -> 8
    // 相当于冒泡排序,只剩一个参数时走递归停止模板函数
};

 

你可能感兴趣的:(C++学习,C++11)