C++ 语言特性21 - 别名模板

news/2024/10/8 13:29:00 标签: c++, 开发语言

一:概述

        别名模板是 C++11 引入的,用于为一个模板类型定义别名,从而简化复杂的模板类型定义。它结合了 using 关键字,可以对模板类型进行重新命名,使代码更加简洁和可读。

        1. 作用

  • 定义模板类型的别名
  • 简化复杂的模板类型,如容器、指针等。

        2. 语法

template<typename T>
using AliasName = ExistingType<T>;

//例子
#include <vector>

// 将 std::vector<T> 别名为 Vec<T>
template<typename T>
using Vec = std::vector<T>;

int main() {
    Vec<int> v = {1, 2, 3};  // 实际上是 std::vector<int>
}

//Vec<int> 是 std::vector<int> 的别名,通过别名模板,代码变得更加简洁。

二:使用场景 

        1. 简化复杂类型:如果某个模板类型嵌套得非常深,用别名模板可以减少冗长的代码

template<typename T>
using MapType = std::map<std::string, std::vector<T>>;

         2. 自定义智能指针:使用别名模板可以为智能指针(如 std::shared_ptrstd::unique_ptr)创建易于使用的别名。

template<typename T>
using Ptr = std::shared_ptr<T>;

Ptr<int> p = std::make_shared<int>(42);

        3. 替代 typedef:别名模板可以完全替代传统的 typedef,尤其是在处理模板类型时。

typedef std::vector<int> VecInt;  // 传统的 typedef
using VecIntAlias = std::vector<int>;  // 别名模板(推荐方式)

三:与 typedef 的对比

   1. typdef 语法

      typedef 是 C++98 及更早版本中定义类型别名的方式。

typedef ExistingType NewType;


//例子
typedef int Integer;  // 将 int 定义为 Integer
typedef int* IntPtr;  // 将 int* 定义为 IntPtr

Integer a = 10;
IntPtr p = &a;

   2.typedef 特点

  • 简单类型别名typedef 可以为基本类型、指针、函数指针、数组等定义别名。
  • 语法复杂typedef 在面对复杂的类型声明时,语法显得比较繁琐且不直观。例如函数指针的 typedef 语法容易混淆。

   3.typedef 局限性

  • 不支持模板typedef 无法与模板配合使用,无法定义模板类型的别名。

    4. 使用建议

        在现代 C++ 中,推荐使用 using 来替代 typedef,因为它的语法更简洁明了,但在现代项目中,typedef 基本已被 using 所取代。

四:与 typename 的对比

        typename 是一个用于声明模板参数或在模板中指定嵌套依赖类型的关键字。它的主要作用是告诉编译器:某个标识符是一个类型而非变量或其他东西。typename 在模板编程中非常重要,用于区分嵌套依赖类型(dependent type)和其他非类型成员。

   1. typename 作用

  • 声明模板参数:作为类型声明的一部分,表明这是一个类型。
  • 解决依赖类型问题:当类型依赖于另一个模板参数时,typename 用于明确告知编译器该标识符是类型而非变量

   2. typename 语法

template<typename T>
class MyClass {
public:
    typename T::NestedType member;  // 声明嵌套类型
};
template<typename T>
class MyClass {
public:
    typename T::value_type getValue(T container) {
        return container[0];
    }
};

int main() {
    std::vector<int> vec = {1, 2, 3};
    MyClass<std::vector<int>> obj;
    int value = obj.getValue(vec);
}


//在这个例子中,T::value_type 是一个依赖类型,使用 typename 明确告诉编译器它是一个类型。

3. 何时需要使用 typename 

        当在模板类或函数中使用某个依赖类型时,必须用 typename 来告知编译器这个符号是类型而不是变量或函数名。例如

template<typename T>
void func() {
    typename T::value_type x;  // T::value_type 是依赖于模板参数 T 的类型
}

//如果省略 typename,编译器会认为 T::value_type 是一个静态成员,而非类型,从而导致编译错误。

 4. 使用场景

  • 使用别名模板:当你希望简化复杂的模板类型定义,或为模板类/函数提供更简洁的命名时,使用别名模板。
  • 使用 typename:当你在模板中遇到依赖类型时(尤其是在嵌套模板结构中),使用 typename 来帮助编译器正确解析这个符号为类型。
// 使用别名模板简化模板类型
template<typename T>
using Ptr = std::shared_ptr<T>;

// 使用 typename 解决依赖类型问题
template<typename T>
void func() {
    typename T::NestedType x;  // T::NestedType 是依赖类型
}

//总之,别名模板用于为模板类型定义别名,简化代码,而 typename 则用于在模板中声明某个标识符为类型,尤其是在处理依赖类型时显得尤为重要。


http://www.niftyadmin.cn/n/5694211.html

相关文章

Chromium 关闭 Google Chrome 后继续运行后台应用功能分析c++

此功能允许关闭 Google Chrome 后继续运行后台&#xff0c;控制此功能的开关是 // Set to true if background mode is enabled on this browser. //更改此值可以修改默认开启关闭 inline constexpr char kBackgroundModeEnabled[] "background_mode.enabled"; …

一文讲清楚退耦电容的位置摆放及其过孔设计

文章目录 一、电容的基础知识二、滤波、去耦和旁路的区别三、电源退耦时电容摆放及过孔设计&#xff1a;1&#xff0e;对电容位置摆放的要求&#xff1a;2&#xff0e;过孔设计常见错误分析3&#xff0e;降低过孔引入的寄生电感4&#xff0e;分析盘中孔工艺 四、结论 在PCBlayo…

微信公众号菜单栏----第⑦篇

如果你是新手小白&#xff0c;请从微信公众号开发第一篇看起&#xff1a;微信公众号开发-接口配置信息&#xff08;第①篇&#xff09;_微信公众号 接口配置信息怎么设置-CSDN博客 代码&#xff1a; <?php// 获取菜单配置数据$menuConfig array(button > array(array(…

传统流程图和N-S流程图的区别

传统流程图和N-S流程图在表示算法和逻辑结构时有不同的特点和用途。以下是它们的主要区别&#xff1a; ### 传统流程图 1. **符号多样**&#xff1a;传统流程图使用多种几何形状表示不同的操作类型&#xff0c;如椭圆表示开始和结束&#xff0c;平行四边形表示输入输出&#…

JavaScript 与 HTML 的结合

在 HTML 页面中嵌入 JavaScript 代码是实现动态效果和交互功能的关键一步。下面是一些常用的方法来实现 JavaScript 与 HTML 的结合。 内联方式&#xff1a;可以直接在 HTML 元素的事件属性中嵌入 JavaScript 代码。例如&#xff0c;可以在按钮的 onclick 属性中添加 JavaScri…

信息安全工程师(38)防火墙类型与实现技术

一、防火墙类型 按软、硬件形式分类 软件防火墙&#xff1a;通过软件实现防火墙功能&#xff0c;通常安装在个人计算机或服务器上&#xff0c;用于保护单个设备或小型网络。硬件防火墙&#xff1a;采用专门的硬件设备来实现防火墙功能&#xff0c;通常部署在企业网络边界或数据…

LeetCode 3310. 移除可疑的方法

LeetCode 3310. 移除可疑的方法 你正在维护一个项目&#xff0c;该项目有 n 个方法&#xff0c;编号从 0 到 n - 1。 给你两个整数 n 和 k&#xff0c;以及一个二维整数数组 invocations&#xff0c;其中 invocations[i] [ai, bi] 表示方法 ai 调用了方法 bi。 已知如果方法 k…

Linux源码阅读笔记-USB驱动分析

基础层次详解 通用串行总线&#xff08;USB&#xff09;主要用于连接主机和外部设备&#xff08;协调主机和设备之间的通讯&#xff09;&#xff0c;USB 设备不能主动向主机发送数据。USB 总线采用拓扑&#xff08;树形&#xff09;&#xff0c;主机侧和设备侧的 USB 控制器&a…