CPP模板元入门,两个关键字[CPP template-3]

本文还是模板元的入门篇,上一篇文章讲了基础的语法(参见我的专栏),这里讲一下模板元中常用的两个关键字,typeiddecltype。题外话,CPP中做函数常用的关键字,不算模板元的话,比较特殊的就算sizeof了,C真是惜字如金啊。但是为了模板元的特性,CPP竟然一下子推出两个关键字,看来确实有够重视,有够有难度。

KEYW:Typeid

typeid 运算符是在 C++98 标准中就已经引入的关键字,它用于在运行时获取一个表达式的类型信息,通常与 std::type_info 类一起使用,后者可以通过 typeid 运算符返回的结果进行查询。(关键字是不能通过语法实现的,因为它本身是语法的一部分)

#include <iostream>
#include <typeinfo> 


int main() {
    int myInt = 5;
    double myDouble = 3.14;
    const std::type_info& intType = typeid(myInt);
    const std::type_info& doubleType = typeid(myDouble);

    std::cout << "myInt is of type: " << intType.name() << std::endl;
    std::cout << "myDouble is of type: " << doubleType.name() << std::endl;

    return 0;
}
将type_info作为成员

std::type_info 对象的赋值操作并不像普通的数据类型那样直接。因此,你需要使用构造函数初始化列表来正确初始化 itemname 成员。

template <class T>
struct mexp
{
    T item;
    const std::type_info& itemname;

    mexp(const T& val)
        : item(val), itemname(typeid(val))  // 使用初始化列表
    {
    }
};

int main()
{
    mexp<int> expint(14);
    cout << expint.item << endl;
    cout << expint.itemname.name() << endl;
}

const std::type_info& itemname;这个句子声明itemname是一个 引用类型,
怎么保证引用的对象不会被注销的

  1. typeid(val) 的生命周期typeid(val) 返回的 std::type_info 对象是静态存储期的,即它在程序运行期间始终存在。这确保了 itemname 引用的是一个有效的对象。
  2. 构造函数内初始化itemname 在构造函数的初始化列表中被初始化为 typeid(val),这个引用在 mexp 对象的整个生命周期内都是有效的,因为 typeid(val) 的返回对象是静态的。

KEYW:decltype

decltype是CPP11引入的关键字,用于推导表达式的类型。值得指出的是,它不会去计算表达式,只是去计算类型并且返回

使用方法如下

 int i = 4;
    decltype(i) a; //推导结果为int。a的类型为int。

 using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
    using ptrdiff_t = decltype((int*)0 - (int*)0);
    using nullptr_t = decltype(nullptr);

 vector<int >vec;
    typedef decltype(vec.begin()) vectype;
    for (vectype i = vec.begin; i != vec.end(); i++)
    {
        //...
    }

重用匿名类型

在C++中,我们有时候会遇上一些匿名类型,如:

struct 
{
    int d ;
    doubel b;
}anon_s;

而借助decltype,我们可以重新使用这个匿名的结构体:

decltype(anon_s) as ;//定义了一个上面匿名的结构体

追踪函数的返回值类型

泛型编程中结合auto,用于追踪函数的返回值类型.这也是decltype最大的用途了。

template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
//这个写法->是显式的指明auto的类型
{
    return x*y;
}

逗号运算搭建匹配空间

匹配空间是我自己在记笔记的时候用的名词(感觉还是挺贴合实际意思的),大家可以参考一下。我们使用SFINAE的时候,总是希望能够多来一些可以匹配的空位,让我们可以提出期望,一般来说,

  • 有模板列表(名称依赖技术)
  • 对模板实参列表中,有偏特化和具体化(全特化)技术
  • 对模板函数,有返回值,和参数列表,还有函数体可以供操作
  • 对类模板,有助手嵌套类+绑定,你还可以写模板函数,这很棒

但是,这些空间总是有限的,所以我们需要搭建匹配空间。下面是逗号匹配空间,在技巧总结中,还有第二种匹配空间

struct MyType {
    int foo();
};

template <typename T>
auto check_foo(int) -> decltype(std::declval<T>().foo(), std::true_type());

template <typename T>
auto check_foo(...) -> std::false_type;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值