• C++ template 学习归纳总结4


    我们在这篇文章来说说typename关键字吧。这个关键字是在c++的标准化过程中引入的,目的在于说明template中的某个表示符号是一个类型,而不是其他的东西,看下面的代码:

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

    第一个typename我就不多说了,大家都知道,我来说一下第二个。他的意思是说T::SubType是class T内部定义的一个类型,从而ptr是一个指向【T:SubType类型】的指针。

    如果在上面的代码中,没有第二个typename关键字的话,编译器会以为SubType是class Type的一个static成员。于是会被编译器理解为一个具体的东西,从而导致T::SubType * ptr 所表达的意思是两个数进行相乘。

    关于这个知识的应用比较多的是STL中,比如:

    #include <iostream> 
    
    // print elements of an STL container 
    template <typename T> 
    void printcoll (T const& coll) 
    { 
        typename T::const_iterator pos;  // iterator to iterate over coll 
        typename T::const_iterator end(coll.end());  // end position 
    
        for (pos=coll.begin(); pos!=end; ++pos) { 
            std::cout << *pos << ' '; 
        } 
        std::cout << std::endl; 
    } 

    下面我们来看看另外一个有意思的问题。那就是”.template”,大家仔细查看下面的代码:

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

    大家注意到没有,。这个例子中的“.template”比较怪,但是如果没有他的话,那么编译器无法知道后面的“<”是模板参数的开始。而不是一个小于号。注意,只有当位于 点号之前的物件取决于某一个template parameter的时候,这种情况才会发生,以上的例子中,bs受控于N。也就是显式指明模板函数调用。可以理解为指名点姓的调用模板成员函数而非普通的。

    结论是“.template”或者”->template”记号只能在templates中使用。而且他们必须紧跟在于template parameter相关的某个物件。

    其实这里关于这个”.template”,笔者也没有搞懂,不知道哪位大牛搞懂了,麻烦指教一下,谢谢了。

    下面我们来看看成员模板:

    先看看下面的例子:

    Stack<int> intStack1, intStack2;   // stacks for ints 
    Stack<float> floatStack;           // stack for floats 
    … 
    intStack1 = intStack2;   // OK: stacks have same type 
    floatStack = intStack1;  // ERROR: stacks have different types 
    

    默认的赋值运算要求左右两边拥有相等的类型。但是如果把赋值运算定义为一个模板,就可以使得类型不同,但是元素可以隐式转换,比如:

    template <typename T> 
    class Stack { 
      private: 
        std::deque<T> elems;   // elements 
    
      public: 
        void push(T const&);   // push element 
        void pop();            // pop element 
        T top() const;         // return top element 
        bool empty() const {   // return whether the stack is empty 
            return elems.empty(); 
        } 
    
        // assign stack of elements of type T2 
        template <typename T2> 
        Stack<T>& operator= (Stack<T2> const&); 
    }; 

    我们来实现它看看:关键代码如下:

    template <typename T> 
     template <typename T2> 
    Stack<T>& Stack<T>::operator= (Stack<T2> const& op2) 
    { 
        if ((void*)this == (void*)&op2) {    // assignment to itself? 
            return *this; 
        } 
    
        Stack<T2> tmp(op2);             // create a copy of the assigned stack 
    
        elems.clear();                  // remove existing elements 
        while (!tmp.empty()) {          // copy all elements 
            elems.push_front(tmp.top()); 
            tmp.pop(); 
        } 
        return *this; 
    } 

    下面我们测试一下啊:

    Stack<int> intStack;     // stack for ints 
    Stack<float> floatStack; // stack for floats 
    … 
    floatStack = intStack;   // OK: stacks have different types, 
                             //     but int converts to float 
    

    当然这个运算并不改变stack和其元素的类型,赋值完成转换,floatstack返回的任然是float。但是这个技术并不是说任何两个类型都能进行赋值,比如下面的代码就不行:

    Stack<std::string> stringStack;  // stack of ints 
    Stack<float>       floatStack;   // stack of floats 
    … 
    floatStack = stringStack;  // ERROR: std::string doesn't convert to float 
    
    

    你知道为什么了吗?

    当然,和以前一样,你也可以在将内部容器的类型也参数化:

    template <typename T, typename CONT = std::deque<T> > 
    class Stack { 
      private: 
        CONT elems;            // elements 
    
      public: 
        void push(T const&);   // push element 
        void pop();            // pop element 
        T top() const;         // return top element 
        bool empty() const {   // return whether the stack is empty 
            return elems.empty(); 
        } 
    
        // assign stack of elements of type T2 
        template <typename T2, typename CONT2> 
        Stack<T,CONT>& operator= (Stack<T2,CONT2> const&); 
    }; 

    此时的赋值运算实现代码为:

    template <typename T, typename CONT> 
     template <typename T2, typename CONT2> 
    Stack<T,CONT>& 
    Stack<T,CONT>::operator= (Stack<T2,CONT2> const& op2) 
    { 
        if ((void*)this == (void*)&op2) {    // assignment to itself? 
            return *this; 
        } 
    
        Stack<T2> tmp(op2);              // create a copy of the assigned stack 
    
        elems.clear();                   // remove existing elements 
        while (!tmp.empty()) {           // copy all elements 
            elems.push_front(tmp.top()); 
            tmp.pop(); 
        } 
        return *this; 
    } 
  • 相关阅读:
    CV 第十一课 Segmentation Localization Detection 下
    面经
    overfitting问题
    CV 第十一课 Segmentation Localization Detection 上
    CV 第十一课 Classification + Localization 中
    SVM的特点
    UNSW CV第二课 上 Image Prepocessing
    UNSW CV Assignment1
    UNSW CV 第一课 下 投影 RGB HSV
    HDU 4350
  • 原文地址:https://www.cnblogs.com/rollenholt/p/2384871.html
Copyright © 2020-2023  润新知