ADL без шаблонов - PullRequest
       12

ADL без шаблонов

1 голос
/ 14 июля 2011

Можно ли показать мне пример ADL без использования шаблонов? Никогда не видел что-то подобное. Я имею в виду что-то вроде здесь . В частности, меня интересует пример, в котором это приводит к некоторой ловушке, как в упомянутом.

EDIT:

Я думаю, что ответ Томалака может быть расширен до ловушки. Учтите это:

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 из неназванного пространства имен будет вызываться, но вместо этого вызывается другое.

Ответы [ 3 ]

4 голосов
/ 14 июля 2011

Я не могу показать вам что-то, что может привести к ловушке, но я могу продемонстрировать ADL, работающий без шаблонов :

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

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

Обратите внимание, что тип lol должен быть class-type; Изначально, как вы видели, я попробовал встроенный, но он не работал.

2 голосов
/ 14 июля 2011

Нет шаблонов.
Использование 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);
}
2 голосов
/ 14 июля 2011

Уловка для путаницы заключается в создании сценария, в котором аргументы функции являются взаимозаменяемыми или конвертируемыми, и 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 или разрешение перегрузки.

...