Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decltype and the scope operator in C++

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?

like image 808
Milan Stezka Avatar asked Feb 15 '12 10:02

Milan Stezka


People also ask

What is Decltype used for?

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.

What is a scope resolution operator :: used for?

The scope resolution operator :: is used to identify and disambiguate identifiers used in different scopes. For more information about scope, see Scope.

Why scope resolution operator is used in C ++?

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.

What is the major application of scope resolution operator (:: in the classes?

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.


1 Answers

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.

like image 153
JoeG Avatar answered Sep 25 '22 00:09

JoeG