VS2012 — Decltype в качестве параметра шаблона в конце типа возврата

Следующий код работает на gcc и даже на VC11 Nov CTP, но не компилируется с VC11 RTM.

template<typename T>
struct A {
typedef typename T::Type BreakMe;
T x;
};
struct B { typedef int Type; };

template<typename T>
struct C {
static A<T> f(A<T> a) {
return A<decltype(a.x)>();
}
static auto g(A<T> a) -> A<decltype(a.x)> {
return A<decltype(a.x)>();
}
};

int main(int argc, char* argv[])
{
C<B>::f(A<B>());
C<B>::g(A<B>());
return 0;
}

VC11 RTM, по-видимому, не работает, decltype передается в качестве параметра шаблона в возвращаемое значение: он думает «T = unknown». Обратите внимание, что f компилируется нормально, несмотря на использование внутри него decltype.

Это ошибка компилятора в RTM? И если так, есть ли способ обойти это?

1

Решение

Я нашел обходной путь.

Хитрость заключается в том, чтобы передать весь возвращаемый тип в вспомогательную структуру и принудительно разрешить шаблон там. typedef-ing возвращаемого типа в вспомогательной структуре не достаточно, так как параметры шаблона decltyped по-прежнему остаются неизвестными. Тем не менее, установка его в качестве возвращаемого типа функции в вспомогательной структуре, похоже, заставляет тип становиться разрешенным. Затем вы можете просто получить тип возвращаемого значения этой функции (снова используя decltype).

Завершение этого в обходном макросе дает

#if defined(_MSC_VER) && _MSC_VER <= 1700
namespace workarounds {
template<typename T>
struct resolve_template {
static T ret();
};
}
#define RESOLVE_TEMPLATE(A) decltype(::workarounds::resolve_template<A>::ret())
#else
#define RESOLVE_TEMPLATE(A) A
#endif

Добавление этого к вышесказанному дает: http://rise4fun.com/Vcpp/JplI

2

Другие решения

Других решений пока нет …