У меня возникают проблемы с пониманием правил поиска по аргументу (Кенига).
Рассмотрим код ниже:
#include <iostream>
using namespace std;
namespace adl
{
struct Test { };
void foo1(Test const &) { cout << "ADL used (foo1)" << endl; }
void foo2(Test const &) { cout << "ADL used (foo2)" << endl; }
void foo3(Test const &) { cout << "ADL used (foo3)" << endl; }
}
struct foo1
{
foo1() { }
template<class T>
foo1(T const &) { cout << "ADL not used (foo1)" << endl; }
template<class T>
void operator()(T const &) const { cout << "ADL not used (foo3)" << endl; }
};
template<class T> void foo2(T const &)
{ cout << "ADL not used (foo2)" << endl; }
int main()
{
adl::Test t;
foo1 foo3;
(foo1(t));
(foo2(t));
(foo3(t));
}
Его вывод:
ADL не используется (
foo1
)
ADL используется (foo2
)
ADL не используется (foo3
)
Я ожидал, что все они будут использовать ADL, но я был удивлен, что только некоторые из них сделали.
Какие (потенциально кровавые, я знаю) подробности за правилами ADL?
Я достаточно хорошо понимаю концепцию, но у меня проблемы с деталями.
Какие области поиска обыскиваются, когда они обыскиваются и когда они не обыскиваются?
Можно ли вообще сказать, используется ли ADL, не просматривая все #include
файлы перед заданной строкой кода? Я ожидал, что функторы и функции будут вести себя одинаково с точки зрения [не] маскирования ADL, но, очевидно, они этого не делают.
Есть ли способ сила ADL в тех случаях, когда это не делается автоматически (например, как указано выше), и вы не знаете пространства имен класса (например, в шаблоне)?
Ваша проблема на самом деле не с аргументно-зависимым поиском. Прежде всего, зависимый от аргумента поиск, возможно, появляется только при выполнении неквалифицированного поиска функций. При звонке foo1(t)
foo1
является типом и его шаблонный конструктор называется. Так же, foo3(t)
это квалифицированный поиск, потому что foo3
является объектом, и оператор вызова функции ищется в классе объекта foo1
, Единственное место, где поиск аргументов входит в картину, это вызов foo2(t)
где поиск находит кандидатов:
::foo2<adl::Test>(adl::Test const&)
::adl::foo2(adl::Test const&)
Эти две функции передаются для разрешения перегрузки, и, поскольку обе функции одинаково хороши, они соответствуют не шаблонной функции.
Ваш вопрос на самом деле три вопроса:
Других решений пока нет …