zoukankan      html  css  js  c++  java
  • 《c++ templates》学习笔记(10)——第九章 模板中的名称

     

    1       第九章 模板中的名称

    C++是一种上下文相关的语言:也就是说我们不能脱离他的上下文构造。

    1.1    名称的分类

    l         受限名称,如果前面有域解析运算符::,或者成员访问运算符(.->),我们就称该名称为受限名称,比如this->count

    l         如果一个名称依赖于一个模板参数,我们就称他为依赖名称。比如 std::vector<T>::iterator,如果T是模板参数,则他是依赖名称,如果T是一个typedef,则他不是依赖名称。

    1.2    名称查找

    普通查找:在某个类内部定义的成员函数定义中,他会先查找该类和基类的作用域,然后才查找外围的作用域。这种查找也就是非受限名称的查找方式。

    不过还应该添加一项:依赖于参数的查找(即ADL)。

    1.3    ADL=argument-depentent lookup

    在函数调用中,如果名称后面尖括号里面有实参表达式,那么ADL将会查找这些实参的associated class associated namespace

    ADL只能应用于非受限函数名称。这个非受限名称是指这个函数的名称是非受限的

    如果普通查找能够找到该名称,那么将不使用ADL

    我们来看下面的例子:

     

    //9.2

    template<typename T>

    inline T const& max(T const& a, T const& b)

    {

        return a<b? b:a;

    }

     

    namespace BigMath

    {

        class BigNumber{

        public:

            BigNumber(int i):mem(i){};

        private:

            int mem;

     

        public:

            int GetMem() const{

                return mem;

            };

        };

     

        bool operator<(BigNumber const& a, BigNumber const& b)

        {

            return a.GetMem()<b.GetMem();

        }

    }

     

    int _tmain(int argc, _TCHAR* argv[])

    {

        //9.2

        BigMath::BigNumber bigNum1(2), bigNum2(3);

        std::cout<<"max Nums is:"<<max(bigNum1, bigNum2).GetMem()<<std::endl;

        return 0;

    }

    在上面的例子中,正常来说,我们应该看不到BinMath名字空间内的运算符 operator <,除非有特殊规则,那么这个特殊规则就是ADL

    再来看下面的例子:

        namespace X{

            template<typename T> void f(T)

            {

                std::cout<<"int template<typename T> void f(T)"<<std::endl;    

            }

        }

     

        namespace N

        {

            using namespace X;

            enum E{ e1};

            class TryUseTemplateF{};

            void f(E){

                std::cout<<"void f(E) in namespace N"<<std::endl;

            };

        }

     

        void f(int i)

        {

            std::cout<<"void f(int) i="<<i<<std::endl;

        }

    int _tmain(int argc, _TCHAR* argv[])

    {

        //9.2.1

        //9.2.1

        ::f(N::e1); //1

        f(N::e1);    //2

        N::TryUseTemplateF aObj;

        f(aObj);     //3

        return 0;

    }

    编译器在编译其上的3时会报错。说是找不到对应的函数重载。

    可见,在执行ADL的时候,名字空间N中的using directive会被忽略了。因为如果没有忽略的话,它就能够找到名字空间X内的模板函数f,而不是编译出错。

  • 相关阅读:
    php.ini中Magic_Quotes_Gpc开关设置
    This is the Manual for Quagga 1.2.0. Quagga is a fork of GNU Zebra
    Are virtual interfaces supported on Quagga v0.98.3 (on Debian GNU/Linux 2.6.16)?
    [quagga-users 8071] Re: Virtual interfaces / aliases supported?
    quagga-0.99.20mr2.1
    Equal Cost Multipath Load Sharing
    (ECMP) Equal-cost multi-path routing
    Multipath suport not working in quagga 0.98.6
    Android-x86-7.1.1
    Android
  • 原文地址:https://www.cnblogs.com/strinkbug/p/1347054.html
Copyright © 2011-2022 走看看