1

有人可以向我展示一个不使用模板的 ADL 示例吗?从来没有见过这样的事情。我的意思是这里。具体来说,我对导致某些陷阱的示例感兴趣,例如提到的。

编辑:

我认为托马拉克的答案可以扩展到陷阱。考虑一下:

namespace dupa {

    class A {
    };

    class B : public A {
    public:
        int c;
        B() {
        }
    };

   void f(B b) {
       printf("f from dupa called\n");
   }
}

void f(dupa::A) {
    printf("f from unnamed namespace called\n");
}


int main()
{   
    dupa::B b;
    f(b);

    return 0;
}

在这里,我们期望调用来自未命名命名空间的 f,而是调用另一个命名空间。

4

3 回答 3

4

我无法向您展示导致陷阱的东西,但我可以演示ADL 在没有模板的情况下工作:

namespace foo {
   struct T {} lol;
   void f(T) {}
}

int main() {
   f(foo::lol);
}

请注意,lol' 类型必须是class-type; 如您所见,我最初尝试使用内置的,但它不起作用。

于 2011-07-13T21:05:56.557 回答
2

混淆的诀窍是创建一个场景,其中函数的参数是可互换或可转换的,并且 ADL 可能会选择一些可能不是您所期望的东西。我不确定这是否令人印象深刻或只是意料之中

namespace a {
   struct A {};
   void f( A* ) { std::cout << "a::f" << std::endl; }
}
namespace b {
   struct B : ::a::A {};
   void f( B* ) { std::cout << "b::f" << std::endl; }
}

void test() {
   f( new b::B );     // b::f
   a::A* p = new b::B; 
   f( p );            // a::f
}

类型相同,但 ADL 将检查参数的静态类型并将该名称空间添加到搜索中。这反过来意味着确切的静态类型可能使编译器可以看到不同的函数。当 ADL 或重载决议可以应用的参数不止一个时,事情会更加混乱。

于 2011-07-13T21:40:41.133 回答
2

没有模板。
使用 swap() 因为这是最常见的用法。

#include <iostream>

namespace One
{
    class A {};
    void swap(A& lhs, A& rhs) { std::cout << "Swap-One A\n";}
}

namespace Two
{
    class A {};
    void swap(A& lhs, A& rhs) { std::cout << "Swap-Two A\n";}
}


int main()
{
    One::A      oneA_l;
    One::A      oneA_r;
    Two::A      twoA_l;
    Two::A      twoA_r;

    swap(oneA_l, oneA_r);
    swap(twoA_l, twoA_r);
}
于 2011-07-13T21:58:53.557 回答