现在的位置: 首页 > 综合 > 正文

《c++ templates》学习笔记(10)——第九章 模板中的名称

2012年04月26日 ⁄ 综合 ⁄ 共 1747字 ⁄ 字号 评论关闭
 

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,而不是编译出错。

 

抱歉!评论已关闭.