模板编程中的技巧

关键字 typename

在C++标准化过程中,引入关键字typename是为了说明;模板内部的标识符可以是一个类型。譬如下面的例子:

template<typename T>
class MyClass{
    typename T::SubType *ptr;
    ...
};

  上面的程序中,第2个typename被用来说明:SubType是定义与类T内部的一种类型。因此,ptr是一个指向T::SubType类型的指针。

  如果不使用typename,SubType就会被认为是一个静态成员,那么它应该是一个具体的变量或对象,于是,下面表达式:

T::SubType *ptr;

  会被看作是类T的静态成员SubType和ptr的乘积。

.template构造

我们在引入typename之后,发现了一个很相似的问题。考虑下面这个使用标准bitset类型的例子:

template<int N>
void printBitset(std::bitset<N> const& bs)
{
    std::cout<<bs.template to_string<char,char_traits<char>,allocator<char> >();
}

  本例中有一个奇怪的构造:.template。如果没有使用这个template,编译器将不知道下列事实:bs.template后面的小于号(<)并不是数学中的小于号,而是模板实参列表的起始符号;那么只有在编辑器判断小于号(<)之前,存在依赖于模板参数的构造,才会出现这种问题。在这个例子中,传入参数bs就是依赖于模板参数N的构造。

使用this->

  对于基类的类模板,自身使用名称x并不一定等同于this->x。即使该x从基类继承获得的,也是如此。例如:

template <typename T>
class Base{
    public:
        void exit();
};

template<typename T>
class Derived:Base<T>{
    public:
        void foo() {
            exit();  //调用外部的exit()或者出现错误
        }
};

  在这个例子中,在foo()内部决定要调用哪一个exit()时,并不会考虑基类Base中定义的exit()。因此,你如果不是获得一个错误,就是调用了另一个exit()。

  注意:对于那些在基类中声明,并且依赖于模板参数的符号(函数或者变量等),你应该在它们前面使用this->或者Base<T>::。如果希望完全避免不确定性,你可以(使用诸如this->和Base<T>::等)限定(模板中)所有的成员访问。

时间: 2024-08-27 16:17:30

模板编程中的技巧的相关文章

C++模板编程中只特化模板类的一个成员函数

模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全部重写该模板类的所有成员函数,不但会增加工作量,也不利于代码的维护. 例如下面的类模板A,只有在模板参数是char*时才需要特化成员函数func(),但其他的成员函数都不需要特化: 1 template <typename _Ty> 2 struct A 3 { 4 // 其他成员函数a 5 //

C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)

转自:https://www.cnblogs.com/zhoug2020/p/6581477.html 模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全部重写该模板类的所有成员函数,不但会增加工作量,也不利于代码的维护. 例如下面的类模板A,只有在模板参数是char*时才需要特化成员函数func(),但其他的成员函数都不需要特化: 1 templ

C++ 11可变参数接口设计在模板编程中应用的一点点总结

概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量(或属性,C#中属性和成员变量还是有区别的): 类的成员方法: 从编译器的角度看,我们必须明确指定以上3部分,才算完整地定义了一个类并且编译通过. 所谓的“类弱化”,是指类的设计者在定义类的时候,并没有完整定义一个类,而是把类的其中一部分的定义留给类的使用者. 从传统才c++98看,通过模板类,使用

模板编程中的几点问题

类模板中头文件和源文件分离的编译问题 1.在泛型编程时, 声明和实现要放置在一起 (因为某些编译器不支持分离) 2.非泛型编程 声明和实现分开 可以为模板指定默认类型 template<typename T=int> class Stack{ } Stack<> stack;//Stack<int> stack; //stack is a stack for int 模板中放置非类型参数 template<typename T, int capacity>

提高效率—编程中的技巧

前几天学习了牛腩--新闻发布系统,里面提到了一些编码技巧,总结了一下和大家分享,有时候就会因为你不知道的这一小点能提升你很高的工作效率! 1.连续按两下tab键,对应的代码段就会自动添加(如:if判断,for循环) 2.Ctrl+k&Ctrl+D(将代码段排序) 3.未编写完成哪里,特别方便! 4.#region + 名称      (可以将一些代码块放到一起) 内容段 #endregion 查找位置:编辑-IntelliSense(I)-插入代码段 快捷键:Ctrl+k & Ctrl+x

Thinkphp编程中几种常见的实用技巧讲解

在Thinkphp编程中集成了很多用起来非常方便的方法.对于刚接触的编程人员来说,可谓是只要掌握并灵活运用了,那么就可以达到事半功倍的效果了,下面就来为大家详细的讲解一下. 1. getField getField的方便之处在于可以获取一个值,一个数组,或者一组键值对. 接下来举三个例子简单说明. A. 获取一个值. 在修改密码的方法中,要验证旧密码是否匹配.现已知用户id为$uid. 则$old_pass = $Model->where("uid='$uid'")->ge

0x3f3f3f3f...编程中无穷大常量的设置技巧

转自 http://aikilis.tk/ 如果问题中各数据的范围明确,那么无穷大的设定不是问题,在不明确的情况下,很多程序员都取0x7fffffff作为无穷大,因为这是32-bit int的最大值.如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择,但是在更多的情况下,0x7fffffff并不是一个好的选择. 很多时候我们并不只是单纯拿无穷大来作比较,而是会运算后再做比较,例如在大部分最短路径算法中都会使用的松弛操作:if (d[u]

编程中无穷大常量的设定技巧【0x3f3f3f3f】

编程中无穷大常量的设定技巧 如 果问题中各数据的范围明确,那么无穷大的设定不是问题,在不明确的情况下,很多程序员都取0x7fffffff作为无穷大,因为这是32-bit int的最大值.如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择,但是在更多的情况 下,0x7fffffff并不是一个好的选择. 很多时候我们并不只是单纯拿无穷大来作比较,而是会运算后再做比较,例如在大部分最短路径算法中都会使用的松弛操作: if (d[u]+w[u]

编程中无穷大常量的设定技巧

Posted on 2012 年 11 月 21 日 by Aikilis 如 果问题中各数据的范围明确,那么无穷大的设定不是问题,在不明确的情况下,很多程序员都取0x7fffffff作为无穷大,因为这是32-bit int的最大值.如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择,但是在更多的情况 下,0x7fffffff并不是一个好的选择. 很多时候我们并不只是单纯拿无穷大来作比较,而是会运算后再做比较,例如在大部分最短路径算法中