C++设计新思维(泛型编程与设计模式之应用)之常整数映射为类别(2.4)

文章介绍了如何通过模板偏特化和全特化来解决在编译期根据类型特性调用不同函数的问题。以NiftyContainer为例,展示了如何使用Int2Type结构体避免在多态和非多态类型间切换时的编译错误,实现编译器在编译期进行函数选择,确保代码的正确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

技术

模板偏特化,模板全特化

应用

1、有必要根据一个编译期常数调用一个或数个不同的函数
2、有必要在编译器实施"分派"(dispatch)

例子

如果打算在执行期进行分派(dispatch),可使用if-else或switch语句。大部分时候其执行期成本都微不足道。然后你还是无法常常那么做,因为if-else语句要求每一个分支都得编译成功。

假设你想设计一个泛型容器NiftyContainer,它将元素类型参数化:

template <class T>
class NiftyContainer
{
	...
	// 假设NiftyContainer内含指针,指向类型为T的对象。
};

为了复制NiftyContainer里的某个对象,你想调用其拷贝构造函数(针对非多态类)或虚函数clone()(针对多态类型)。
你以一个bool来作为调用哪种函数的条件

template <class Tbool isPolymorphic>
class NiftyContainer
{
	...
	void doSomething()
	{
		T *pSomeObj = ...;
		if (isPolymorphic) { // 多态
			T *pNewObj = pSomeObj->clone(); 
		} else { // 非多态
			T *pNewObj = new T(*pSomeObj);
			// T *pNewObj = new T();
			// *pNewObj = *pSomeObj;
		}
	}
};

问题是,编译器并不一定都会编译成功,如果使用多态算法,那么对于任何一个未定义clone函数的类或者clone是private的类,都将使doSomething函数无法编译成功。而对于非多态类型,如果禁用了拷贝构造或者拷贝构造在private区域也同样将无法编译成功。所以想要编译成功,则T类型必须同时具有clone()拷贝构造函数才能编译成功。
如果我只需要clone拷贝构造函数中的一种呢?
虽然有很多种解法,但是以下这种解法最简单易理解。

template <int v>
struct Int2Type
{
	enum { value = v };
};

template <class T, bool isPolymorphic>
class NiftyContainer
{
public:
	void doSomething(T *pObj)
	{
		doSomething(pObj, Int2Type<isPolymorphic>());
	}

private:
	void doSomething(T *pObj, Int2Type<true>)
	{
		T *pNewObj = pObj->clone();
	}
	
	void doSomething(T *pObj, Int2Type<false>)
	{
		T *pNewObj = new T(*pObj);
	}
};

这种手法在STL代码中很常见,只是形式略有不同而已。
这种小技巧之所以有效,最主要原因是编译器不会编译一个未被使用到的template函数,只会对它做语法检测。至于此技巧之所以有用,是因为在template代码中大部分情形要在编译期做流程分派动作。

测试
/*************************************************************************
    > File Name: main.cc
    > Author:
    > Brief:
    > Created Time: Mon 23 Jan 2023 03:46:27 PM CST
 ************************************************************************/

#include <iostream>
using namespace std;

template <int v>
struct Int2Type
{
    enum
    {
        value = v
    };
};

template <class T, bool isPolymorphic>
class NiftyContainer
{
public:
    void doSomething(T *pObj)
    {
        doSomething(pObj, Int2Type<isPolymorphic>());
    }

private:
    void doSomething(T *pObj, Int2Type<true>)
    {
        T *pNewObj = pObj->clone();
    }

    void doSomething(T *pObj, Int2Type<false>)
    {
        T *pNewObj = new T(*pObj);
        delete pNewObj;
    }
};

class Test
{
public:
    Test() { printf("%s()\n", __func__); }
    Test(const Test &o) { printf("%s(const Test &o)\n", __func__); }
    ~Test() { printf("%s()\n", __func__); }
};

int main(int argc, char **argv)
{
    Test t;
    NiftyContainer<Test, false> container;
    container.doSomething(&t);
    return 0;
}

在这里插入图片描述

### C++ 编程语言的全面学习资料知识点汇总 #### 一、C++ 的基本概念发展历史 C++ 是一种通用的、面向对象的编程语言,最初由 Bjarne Stroustrup 在 1983 年于贝尔实验室开发。作为一种强大的编程语言,它不仅继承了 C 语言的优点,还引入了许多新的特性,使其能够支持多种编程范式,包括过程化编程编程以及面向对象编程[^2]。 #### 二、C++ 的主要特性和功能 以下是 C++ 中的一些核心特性及其作用: - **面向对象编程 (OOP)**:通过类和对象实现封装、继承和多态等机制,使代码更加模块化和可维护。 - **模板编程**:允许编写独立于类的函数和类,从而提高代码重用率。 - **标准库的支持**:C++ 提供了一个丰富的标准库(STL),其中包括容器、算法、迭代器等功能组件。 - **指针操作**:提供了对内存管理的高度控制能力,但也增加了复杂度和潜在风险。 - **多重继承**:其他一些 OOP 语言不同的是,C++ 支持单个类从多个基类派生的能力。 #### 三、基础知识体系概览 ##### (1)环境搭建第一个程序 了解如何安装配置适合自己的 IDE 或编辑器,并完成简单的 Hello World 示例。这一步骤通涉及编译器的选择(如 GCC, Clang 等)、项目结构设置等内容[^3]。 ##### (2)变量声明及数据类 熟悉各种内置的数据类整数 int、浮点数 double、布尔 bool 等)以及它们之间的转换规则;同时也要学会定义量的方式 const 关键字的应用场景[^3]。 ##### (3)运算符表达式计算 掌握算术运算符 (+,-,*,/) ,关系比较 (!=,<>) 和逻辑组合(&&,||) 方法,在此基础上构建条件判断语句 if...else 结构或者循环 while/do..while 控制流程走向。 ##### (4)数组字符串处理 研究固定大小静态分配方式的一维或多维数组形式表示集合元素存储位置关系;对于动态需求则可以考虑 vector 容器替代传统做法。另外关于字符序列的操作技巧也是不可忽视的一部分[^1]。 ##### (5)函数设计原则 讨论参数传递模式(值拷贝 vs 引用交换)、返回值得设定还有递归调用的概念解释说明等等细节要点[^1]。 #### 四、进阶主题探索方向 当掌握了以上提到的基础部分之后就可以尝试接触更高层次的知识点了比如但不限于以下几个方面: - STL 库深入剖析 – 掌握向量(vector), 列表(lists)映射(map)等高效数据结构的实际运用场合; - 文件流 I/O 操作– 实现持久化的读写外部资源文件的功能扩展; - 多线程并发模– 解决实际工程项目中的性能瓶颈问题; - 设计模式实践案例分享– 基于真实世界业务背景下的抽象思维训练机会。 ```cpp #include <iostream> using namespace std; class HelloWorld { public: void sayHello() { cout << "Hello, world!" << endl; } }; int main(){ HelloWorld hw; hw.sayHello(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值