C++泛型模板约束深入讲解

CPP参考:(新标准)

传送门

模板对于类型的约束:

约束 template_get_size 泛型T只允许接受类型:list<T>,其实为 C/C++ 泛型模板例化特性,但与泛型模板例化略微有些区别,因为是带泛型类型约束条件的特例化。

template<typename T>
class list {
public:
    int count = 0;
};
template<typename T>
struct template_get_size;
template<typename T>
struct template_get_size<list<T> > {
    inline std::size_t size(list<T>& v) {
        return v.count;
    }
};
int main(int argc, const char* argv[]) noexcept {
    list<int> list_;
    list_.count = 100;
    template_get_size<list<int> > list_get_size_;
    printf("%d\n", list_get_size_.size(list_));
    return 0;
}

但,template_get_size<int> 仍然可以尝试编译,从语法层面没有问题,但会编译失败,原因:C/C++ 使用不完整的类型。

人们无法在编译期间来增加更多检查约束的有效性。

例一:

template<typename T>
struct template_get_size {
    static_assert(false, "Type constraints of generic templates are violated.");
};

例二:

template<typename T>
struct template_get_size;
template<typename T>
struct template_get_size<T> {
    static_assert(false, "Type constraints of generic templates are violated.");
};

上述适用于泛型模板类/结构体,同理泛型模板函数仍可以增加泛型约束,只是没有办法向模板类型一样可以明确的约束T到底需要是什么类型,这取决于模板函数内部的实现,根代码粘合剂差不多,但不意味着不能精确限制那些T类型。

泛型模板类型例化:

class A {};
class B : public A {};
template<typename T>
class say;
template<>
class say<A> {};

例如:人们需要T是一个指针,那么有以下几种方法约束:

案例一:

template<typename T>
void foo(const T* v) {}

案例二:

template<typename T>
void foo(const T& v) {
    typedef typename std::remove_pointer<T>::type element_type;
    element_type* p = NULL;
}

如果:

人们需要T是一个基类,那么这种似乎不需要模板来实现,如果是模板大约是这样的形式:

约束T必须是A类或其派生类型,但使用该模板函数的开放人员只有两个途径搞清楚T到底被约束为什么。

即:1、函数注释上明确T的约束类型,2、查看模板函数的内部实现,不像C#中明确为泛型模板类型 T 增加显示一致性的 where T 约束条件。

class A {};
class B : public A {};
template<typename T>
void foo(const T* v) {
    A* a = const_cast<T*>(v);
}
int main(int argc, const char* argv[]) noexcept {
    B b;
    foo(&b);
    return 0;
}

一个好的建议是:

每个泛型模板的类型约束都应在类型/函数注释上明确指出,这样使用模板的开发人员不需要尝试预编译代码或阅读模板代码实现来判定模板代码约束条件。

到此这篇关于C++泛型模板约束深入讲解的文章就介绍到这了,更多相关C++泛型模板约束内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ primer超详细讲解泛型算法

    目录 初识泛型算法 只读算法 写容器算法 定制操作 lambda表达式 lambda捕获和返回 再探迭代器 插入迭代器 iostream迭代器 反向迭代器 初识泛型算法 只读算法 只读取输入范围内的函数,不改变元素,find,accumula也是如此 (1)accumulate算法为求和算法,前两个参数指出求和元素范围,第三个是和的初值,例: int sum=accumulate(v.begin(),v.end(),0) (2)操作两个序列的算法 equal算法,确定两个序列是否保存相同的值,将

  • C++泛型编程Generic Programming的使用

    目录 一.容器 array vector deque list map 键值对key/value 二.迭代器iterator(泛型指针) 三.泛型算法Generic Programming insert()插入 erase()删除 find()用于无序搜索,搜素范围[first, last), 返回iterator, 找不到则返回last copy() 复制 泛型编程最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库. 所谓通用的标准容器库,就是要能够做到,比如用一个

  • C++使用泛型导致的膨胀问题

    目录 临峰不畏博主从事C++软件开发多年,由于之前的开发环境都是资源充足的服务器,不用考虑磁盘空间的问题.最近打算在智能家居主机的嵌入式平台上使用C++进行开发.FLASH存储空间有限,这是必须要考虑的因素,一定要重视. 如下定义两个list,元素类型不同: list<int> l1; list<string> l2; 如果是用C语来做应该怎么办?它会对应list<int>写一套代码,再对list<string>写一套.每套都有相同的成员函数,只是变量类型各

  • C++泛型编程综合讲解

    目录 函数模板 类模板 函数符(Function) 包装器 函数模板 进一步把函数中的或类中的数据类型进一步抽象,这个抽象的类型就叫泛型 模板:函数模板,类模板 模板就是把函数(或类)中的类型抽象出来,有指定类型方可使用 模板可以有默认类型,类模板规则(函数模板,不存在规则):从右到左 模板编译机制: 编译器并不是把函数(类)模板处理成能够处理任何类型的函数(类),而是一个函数(类)的生成器. 函数(类)模板通过具体类型产生不同的函数实例(类实体). 编译器会对函数(类)模板进行两次编译,第一次

  • 详解C++泛型装饰器

    目录 c++ 装饰器 对输出的解释 总结 c++ 装饰器 本文简单写了个 c++ 装饰器,主要使用的是c++ lamda 表达式,结合完美转发技巧,在一定程度上提升性能 #define FieldSetter(name, type, field) \ type field; \ name() {} \ name(const type& field): field(field) { \ cout << "[左值 " << field << &q

  • C++泛型编程函(数模板+类模板)

    目录 一.函数模板 1.函数模板介绍 2.函数模板与重载函数的关系 3.函数模板实现机制 二.类模板 1.类模板基本语法 2.类模板内函数的整体布局[分文件使用类模板] 3.类模板的static与模板类的static 4.数组实现万能容器 前言: 由于C++是静态语言,也就是说使用一个数据的时候必须先指定类型,这样的操作在编译后变量的类型是无法轻易改变的,就导致扩展性太差.或者一个函数需要很多次重载的时候,代码显得冗杂,由此产生了C++函数模板. 一.函数模板 1.函数模板介绍 ① 函数模板的产

  • C++超详细讲解泛型

    目录 1.了解泛型编程 2.函数模板 2.1简单示例 2.2多个模板参数 2.3模板实例化 2.4模板和普通函数同时存在 2.5函数模板不支持定义和声明分离 3.类模板 3.1简单示例 3.2成员函数声明和定义分离 1.了解泛型编程 就好比活字印刷术,可以灵活调整印刷的板块和内容,比只能固定印刷某一个内容的雕版印刷术效率更高,也让印刷术由此得到了更广泛的应用. 在C++中,函数重载和模板的出现,让泛型编程得到了实际的应用.其中模板,就是类似活字印刷术一样的存在. 2.函数模板 八八了那么多没用的

  • C++类模板与函数模板基础详细讲解

    目录 函数模板 类模板 总结 函数模板 当我们想要定义一个可以支持泛型的函数时,就要采用函数模板的方式了.所谓泛型就是可以支持多种类型的操作,比如我们定义一个compare操作,他可以根据传递给他的参数类型动态调用对应的函数版本,实现多种类型的比较. template <typename T> int compare(const T &v1, const T &v2) { if (v1 < v2) return -1; if (v2 < v1) return 1;

  • Java 泛型超详细入门讲解

    目录 1.什么是泛型? 2.泛型是怎么编译的 泛型的编译机制:擦除机制 1.什么是泛型? 泛型其实就是将类型作为参数传递,泛型允许程序员在编写代码时使用一些以后才指定的类型 ,在实例化该类时将想要的类型作为参数传递,来指明这些类型. 为什么要引入泛型? 例如:自己实现一个顺序表 public class MyArrayList { public int[] elem; public int usedSize; public MyArrayList() { this.elem = new int[

  • Java 泛型超详细入门讲解

    目录 1.什么是泛型? 2.泛型是怎么编译的 泛型的编译机制:擦除机制 1.什么是泛型? 泛型其实就是将类型作为参数传递,泛型允许程序员在编写代码时使用一些以后才指定的类型 ,在实例化该类时将想要的类型作为参数传递,来指明这些类型. 为什么要引入泛型? 例如:自己实现一个顺序表 public class MyArrayList { public int[] elem; public int usedSize; public MyArrayList() { this.elem = new int[

  • 比较不错的asp模板引终极讲解(WEB开发之ASP模式)

    作者: 孙立 Email: 17bizAT126.com 写于:2006/3/5 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明 http://sunli.cnblogs.com/archive/2006/03/05/343095.html 关键词:ASP 模板 摘要: 阐述一种全新的ASP模板引擎,实现代码(逻辑)层与HTML(表现)层的分离.这种模板实现方法避免了一 般ASP模板加载模板文件(加载组件)和替换所浪费的资源,实现编译型的模板引擎,提高程序的执

  • C# 泛型的约束

    1.引用类型约束 struct RefSample<T> where T:class         引用类型用Class表示约束,其他的引用类型为具体的约束. 表示对于的约束必须为一个类(引用类型)不能是值类型(int,char,datatime,struct),可以是接口interface 区分,数组为引用类型,因为定义数组时需要new出一个对象. 虽然定义成 RefSample<T> 传入的必须为引用类型 但是RefSample仍然为值类型 2.值类型约束 class Val

  • 最新Java 泛型中的通配符讲解

    目录 一.什么是类型擦除? 二.案例实体准备 三.常用的 ?, T, E, K, V, N的含义 四.上界通配符 < ? extends E> 五.下界通配符 < ? super E> 六.什么是PECS原则? 七.通过一个案例来理解 ?和 T 和 Object 的区别 本文内容如下: 1. 什么是类型擦除2.常用的 ?, T, E, K, V, N的含义3.上界通配符 < ?extends E>4.下界通配符 < ?super E>5.什么是PECS原则6

  • C#泛型相关讲解

    我们在编写程序时,经常 遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法 处理每个数据类型,因为方法的参数类型不同.有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题 的.读完本篇文章,你会对泛型有更深的了解.为什么要使用泛型 为了了解这个问题,我们先看下面的代码,代码省略了一些内容,但功能是实现一个栈,这个栈只能处理int数据类型: 复制代码 代码如

  • C#泛型运作原理的深入理解

    前言# 我们都知道泛型在C#的重要性,泛型是OOP语言中三大特征的多态的最重要的体现,几乎泛型撑起了整个.NET框架,在讲泛型之前,我们可以抛出一个问题,我们现在需要一个可扩容的数组类,且满足所有类型,不管是值类型还是引用类型,那么在没有用泛型方法实现,如何实现? 一.泛型之前的故事# 我们肯定会想到用object来作为类型参数,因为在C#中,所有类型都是基于Object类型的.因此Object是所有类型的最基类,那么我们的可扩容数组类如下: public class ArrayExpandab

  • C#泛型的使用及示例详解

    目录 一.什么是泛型 二.为什么使用泛型 三.泛型类型参数 四.泛型类 五.泛型约束 六.泛型的协变和逆变 七.泛型缓存 这篇文章主要讲解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建项目框架的时候. 一.什么是泛型 泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法来处理不同的数据类型.这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种

  • C#中的==运算符用法讲解

    目录 ==运算符与基元类型 ==运算符与引用类型 ==运算符与String类型 ==运算符与值类型 ==运算符与泛型 总结 ==运算符与基元类型 我们分别用两种方式比较两个整数,第一个使用的是Equals(int)方法,每二个使用的是==运算符: class Program { static void Main(String[] args) { int num1 = 5; int num2 = 5; Console.WriteLine(num1.Equals(num2)); Console.Wr

随机推荐