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?
The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments.
The scope resolution operator :: is used to identify and disambiguate identifiers used in different scopes. For more information about scope, see Scope.
Scope resolution operator in C++ In C++, scope resolution operator is ::. It is used for following purposes. 2) To define a function outside a class. 3) To access a class's static variables.
Use :: for classes and namespaces A scope resolution operator without a scope qualifier refers to the global namespace. You can use the scope resolution operator to identify a member of a namespace , or to identify a namespace that nominates the member's namespace in a using directive.
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:
#if _MSC_VER == 1600
#include <utility>
#define decltype(...) \
std::identity<decltype(__VA_ARGS__)>::type
#endif
Which allows this to compile and work on MSVC10:
std::vector<int> v;
decltype(v)::value_type i = 0;
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 includes std::identity
in its standard library implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With