decltype和C++中的作用域运算符

Mil*_*zka 15 c++ scope decltype operator-keyword c++11

我需要获取实例化模板时提供的类型.请考虑以下示例:

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;
}
Run Code Online (Sandbox Code Playgroud)

此代码的问题是将范围运算符与decltype一起使用.Visual C++ 2010抱怨如下:

错误C2039:'TUnderlying':不是'`global namespace''的成员

我在维基百科上收集了一些关于这个主题的信息:

在评论C++ 0x的正式委员会草案时,日本ISO成员机构指出"范围运算符(::)不能应用于decltype,但它应该是.在获取成员类型的情况下将是有用的(嵌套类型)来自实例,如下所示":[16]

vector<int> v;
decltype(v)::value_type i = 0; // int i = 0;
Run Code Online (Sandbox Code Playgroud)

David Vandevoorde解决了这个和类似的问题,并于2010年3月投票进入了工作文件.

所以我认为Visual C++ 2010没有实现这一点.我想出了这个解决方法:

template <typename T> struct ScopeOperatorWorkaroundWrapper
{
  typedef typename T::TUnderlying TTypedeffedUnderlying;
};

auto Automatic() -> ScopeOperatorWorkaroundWrapper<decltype(FooInt)>::TTypedeffedUnderlying
{
  return ScopeOperatorWorkaroundWrapper<decltype(FooInt)>::TTypedeffedUnderlying();
}
Run Code Online (Sandbox Code Playgroud)

我是否错过了任何更优雅,更简洁的解决方案?

Joe*_*oeG 12

这会透明地将decltype关键字替换为基于模板的变通方法.一旦您不再需要支持MSVC2010,您可以删除宏定义而无需更改任何用户代码:

#if _MSC_VER == 1600
#include <utility>
#define decltype(...) \
  std::identity<decltype(__VA_ARGS__)>::type
#endif
Run Code Online (Sandbox Code Playgroud)

这允许它在MSVC10上编译和工作:

std::vector<int> v;
decltype(v)::value_type i = 0;
Run Code Online (Sandbox Code Playgroud)

请注意,这std::identity不是C++标准的一部分,但在此处依赖它是安全的,因为解决方法仅限于包含std::identity在其标准库实现中的编译器.