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

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


person Argbart    schedule 13.07.2011    source источник
comment
Да, и почему это не работает?   -  person Lightness Races in Orbit    schedule 14.07.2011
comment
@Tomalak Потому что тип lol - это int. см. это.   -  person Luc Danton    schedule 14.07.2011
comment
Я предлагаю вам изменить имя пространства имен, кого-то это может обидеть.   -  person Tomek    schedule 14.07.2011
comment
@Tomek: dupa - это польский эквивалент английского foo - кого это может обидеть, если почти все его используют? ;-)   -  person Pawel Zubrycki    schedule 04.04.2012


Ответы (3)



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

person David Rodríguez - dribeas    schedule 13.07.2011
comment
Обратите внимание, что эффект точно такой же, как и при использовании невиртуальных методов: статический тип определяет, какой из методов используется при перегрузке, и это предусмотрено дизайном: ADL находится в языке, поэтому свободные функции можно использовать как расширения для введите способом, похожим на функции-члены. - person David Rodríguez - dribeas; 14.07.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);
}
person Martin York    schedule 13.07.2011