混沌 IN C++::Argument Dependent Lookup

难度: rel="File-List" href="file:///C:%5CUsers%5CADMINI%7E1%5CAppData%5CLocal%5CTemp%5Cmsohtml1%5C02%5Cclip_filelist.xml">

知识回顾:

Argument Dependent Lookup(Koenig Lookup)

    当函数调用时,根据参数类型定义所在的命名空间或类域中查找函数名或运算符。如下所示。

    namespace NS

{

        struct A{};

        void f(A);

}

 

int main()

{

    NS::A a;

    f(a);

}

                           

main中,并未在main所在的全局域中给出函数f的定义和声明,但是这段代码仍然可以通过编译,这正是Argument Dependent Lookup规则在起作用,在确认f(a)为函数调用时,编译器便开始实施Argument Dependent Lookup规则。

 

对于模板函数,这种查找规则仍然有效。例如

namespace NS

{

    struct A{};

    template<typename T> void f(T);

}

 

int main()

{

    NS::A a;

    f(a);

}

 

在上面的代码中,如果显示指定NS::f的模板参数会发生什么情况呢?

 

f<NS::A>(a);

 

程序无法编译通过!貌似Argument Dependent Lookup不起作用了?确切地说现在编译器并没有实施这种查找规则。在编译器的眼中,这行语句并不是函数调用,而是被看作了

 

(f < NS::A) > (a);

 

用小于比较fNS::A,然后其结果再与a进行大于比较。导致这种情况是因为<NS::A>的部分没有被看作是显示指定的模板参数,因为在main所在的全局域中,并没有函数模板f的声明,也没有任何信息说明f是函数模板。解决的办法就是

 

NS::f<NS::A>(a);

 

现在编译器从f的声明得知f是函数模板,那么<NS::A>也理所当然的被看作是显示指定模板参数的列表。

 

问题:

    代码如下。

 

    namespace NS1

    {

        struct A{};

        template<typename T> void f(A){}

}

 

namespace NS2

{

    template<int I> void f(NS1::A){}

}

 

int main()

{

    NS1::A a;

    using NS2::f;

 

    f<NS1::A>(a);

}

 

思考这段代码,编译器应该如何处理f<NS1::A>

1.  编译失败,f无法和NS1::A进行比较。

2.  编译失败,无法匹配NS2::f的参数,需要一个非类型的模板参数。

3.  编译失败,f未定义。

4.  编译成功,调用NS1::f

5.  编译成功,调用NS2::f

6.  编译失败,二义性,有NS1::fNS2::f的候选匹配。

 

 

答案:

    4. 编译成功,调用NS1::f

 

解析过程:

    首先 using-declarationNS2:f 引入到main函数域中,然后对于f<NS1::A>(a)这一句,此刻编译器就能识别到f是一个函数模板,确认<NS1::A>为显示指定模板参数,接下来就能确认f<NS1::A>(a)是函数调用。在确认是函数调用之后,开始命名查找,首先查找到NS2::f,这是由using-declaration引入到main函数域中的。还没完,接下来开始Argument Dependent Lookupa的类型是定义在NS1中的,还需要在NS1中继续查找f,最后找到了NS1::fNS2::f,而NS2::f的模板参数为非类型模板参数。最符合匹配的就只有NS1::f

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值