I need to obtain the type which was supplied when instantiating a template. Consider the following example:
template <typename T> struct Foo
{
typedef T TUnderlying;
};
static Foo<int> FooInt;
class Bar
{
public:
auto Automatic() -> decltype(FooInt)::TUnderlying
{
return decltype(FooInt)::TUnderlying();
}
};
int main()
{
Bar bar;
auto v = bar.Automatic();
return 0;
}
Problem with this code is using the scope operator together with decltype. Visual C++ 2010 complains like this:
error C2039: 'TUnderlying' : is not a member of '`global namespace''
I gathered some information on the topic on Wikipedia:
While commenting on the formal Committee Draft for C++0x, the Japanese ISO member body noted that "a scope operator(::) cannot be applied to decltype, but it should be. It would be useful in the case to obtain member type(nested-type) from an instance as follows":[16]
vector<int> v;
decltype(v)::value_type i = 0; // int i = 0;
This, and similar issues were addressed by David Vandevoorde, and voted into the working paper in March 2010.
So I reckon the Visual C++ 2010 does not have this implemented. I came up with this workaround:
template <typename T> struct ScopeOperatorWorkaroundWrapper
{
typedef typename T::TUnderlying TTypedeffedUnderlying;
};
auto Automatic() -> ScopeOperatorWorkaroundWrapper<decltype(FooInt)>::TTypedeffedUnderlying
{
return ScopeOperatorWorkaroundWrapper<decltype(FooInt)>::TTypedeffedUnderlying();
}
Did I miss any solution which is more elegant and less verbose?
This transparently replaces the
decltype
keyword with the template based workaround. Once you no longer need to support MSVC2010 you can remove the macro definition without changing any user code:Which allows this to compile and work on MSVC10:
Note that
std::identity
isn't part of the C++ standard, but it's safe to rely on it here as the workaround is limited to a compiler which includesstd::identity
in its standard library implementation.The workaround looks relatively fine but it’s not extensible and the names are horrible1. Why not use
id
?And then:
Untested, but should work.
1 As in, too verbose and even though they describe that it’s a workaround, this may be redundant and not a useful information in most of the situations.
As an alternative, you can easily pull the type out using a function template helper: