• Effective C++ 条款42 了解typename的双重意义


    1. 在template的声明式中,typename的使用和class完全相同,即以下两种声明方式完全相同

    template<typename T>
    template<class T>

    然而typename还有其他用途:指明嵌套从属类型名称.

    2. 嵌套从属类型名称:如果template中某个名称依赖于类型参数,那么它就是从属名称,如果这个从属名称在某个class中呈嵌套装,那么它就是嵌套从属名称,如果它指涉的是某种类型,那么它就是嵌套从属类型名称,例如:

    //这是一个用于接受STL容器作为参数的函数模板
    template<tpyename T>
    void print2nd(const T&container){
        if(container.size()>=2){
            T::const_iterator iter=container.begin();
            int value=*iter;
            std::cout<<value<<endl;
        }
    }
    View Code

    这个函数模板相当简单,它用于打印一个容器的第二个元素,其中value是int类型,它不依赖与类型参数,因此是非从属(non-independent)名称,而const_iterator就是嵌套从属类型名称.

    实际上,这段代码无法通过编译,T::const_iterator存在歧义,它既可能是类T的嵌套类型名称,也有可能是T的static成员,面对这种歧义,C++在遇到嵌套从属名称时,它便假设这个名称不是一种类型,因此遇到T::const_iterator,解析器可能会将const_iterator解析为T的static数据成员,因此报错.

    要解决这个问题,只需要在T::const_iterator之前加上typename关键字即可,即:

    template<tpyename T>
    void print2nd(const T&container){
        if(container.size()>=2){
            typename  T::const_iterator iter=container.begin();
            int value=*iter;
            std::cout<<value<<endl;
        }
    }
    View Code

    注意,typename只能被用来指明嵌套从属类型名称,非嵌套从属类型名称不可使用用typename.此外,typename不可出现在base classes list内的嵌套从属类型名称之前,也不可在member initialization list中作为基类修饰符,例如:

    template<typename T>
    class Derived:public Base<T>::Nested{//不可以用typename
    public:
        explict Derived(int x):Base<T>::Nested(x){//不可以用typename
            typename Base<T>::Nested temp;//可以用typename
            ...
        }
        ...
    private:
        ...
    }
    View Code

    3. 此外,不同编译器对typename相关规则的支持度可能不同,有些编译器接受的代码原本该有typename却遗漏了,原本不该有typename却出现了;还有少数编译器根本就拒绝typename.

  • 相关阅读:
    系统角色权限问题
    解析JQuery Ajax
    JavaScriptSerializer序列化时间处理
    Javascript加载talbe(包含分页、数据下载功能)
    代理模式
    工厂模式
    单例模式
    Oracle内置函数
    Oracle大数据SQL语句优化
    Oracle大数据查询优化
  • 原文地址:https://www.cnblogs.com/reasno/p/4800226.html
Copyright © 2020-2023  润新知