Я только что понял, что попытка получить возвращаемый тип функции через decltype не включает ADL (аргумент-зависимый поиск) на VS2012 (протестировано с использованием cl.exe V17.00.60610.1).
Следующий пример
#include <stdio.h>
#include <typeinfo>
namespace A {
int Func(void const *) {
printf("A::Func(void const *)\n");
return 0;
}
template <typename T> void Do(T const &t) {
Func(&t);
}
template <typename T> void PrintType(T const &t) {
printf("Type: %s\n", typeid(decltype(Func(&t))).name());
}
}
namespace B {
struct XX { };
float Func(XX const *) {
printf("B::Func(XX const *)\n");
return 0.0f;
}
}int main(int argc, char **argv) {
B::XX xx;
A::Do(xx);
A::PrintType(xx);
return 0;
}
дает
B::Func(XX const *)
Type: int
на VS2012
но (что ожидается):
B::Func(XX const *)
Type: f
на gcc 4.7.3.
Таким образом, ADL работает при вызове функции (строка 1 на выходе), но не при использовании внутри decltype на VS2012.
Или я упускаю какую-то другую точку?
Минимальный тестовый пример:
namespace N
{
struct C {};
C f(C) {};
}
N::C c1;
decltype(f(c1)) c2;
Если компилятор не поддерживает ADL внутри decltype, то вышеописанное не скомпилируется.
Мне сказали, что он компилируется, поэтому, возможно, проблема заключается в взаимодействии между ADL и созданием шаблона.
Если вы находите забавным то, что IDE / Intellisense, кажется, выполняет поиск правильно, а компилятор — нет.
Этот пример не показывает ошибок intellisense и a
отображается как тип size_t
при наведении.
#include <iostream>
namespace A
{
struct C {};
size_t f(C*) { return 5U; };
}
namespace B
{
void f(void *) { };
void f2 (A::C x)
{ decltype(f(&x)) a; std::cout << typeid(a).name() << std::endl; }
}
int main (void)
{
A::C c;
B::f2(c);
}
Компилятор останавливается с Error C2182
и жалуется на переменную типа void.
Кажется, проблема не зависит от шаблонов.