There appears to be some discrepancy between compilers as to whether the following code is well formed. In particular, GCC and Clang accept this code -- whereas MSVC rejects it:
template <typename T>
class Bar{};
template <typename T>
struct Foo
{
using element_type = T;
operator Bar<element_type>();
};
template <typename T>
Foo<T>::operator Bar<element_type>()
{
return {};
}
MSVC's rejection message is just a generic:
<source>(11): error C2065: 'element_type': undeclared identifier
The issue only appears to occur when the template argument for the conversion type is a dependent template type, since this is resolved by changing Bar<element_type> to either Bar<T> or Bar<typename Foo<T>::element_type>. I've made a small example on compiler explorer to demonstrate this. This appears to occur from C++11 (possibly older, didn't test) up to C++2a, and is independent of the compiler's versions or flags.
I know that C++ allows dropping the prefixing class-name specifier for types when in the body or parameter list of a class function/constructor definition -- but I'm unsure whether this same short-form is allowed when handling a conversion operator in an out-of-line definition.
Is this an ambiguity in the standard, or a bug in either of the compilers? I'm mostly curious to know how this is defined (or not, as it may be) in the C++ standard.
Edit: To add to the confusion, it appears that MSVC accepts the following code:
template <typename T>
struct Foo
{
using element_type = T;
operator element_type();
};
template <typename T>
Foo<T>::operator element_type() // note: no 'typename' syntax
{
return {};
}
so this doesn't appear to be just an issue caused from conversion to template-dependent type names... I'm suspecting this may be an MSVC bug rather than a discrepancy.