templates,typename,lambda - >依赖名称不依赖?

时间:2011-01-03 22:36:08

标签: c++ templates lambda c++11 typename

考虑:

template < typename Something >
boost::function<void()> f()
{
  typedef typename Something::what type;
  return [](){};
}

在此代码中,您需要typename,因为'what'是一个依赖名称。但请考虑一下:

template < typename Something >
boost::function<void()> f()
{
  return []()
  { 
    typedef typename Something::what type;
  };
}

编译器bitches:“typename不能在模板声明之外使用”

WTF?

这有效:

template < typename Something >
boost::function<void()> f()
{
  return []()
  { 
    typedef Something::what type;
  };
}

创建lambda是什么意思“什么”不再是依赖名称了?或者这只是一个错误?

...嘿校正。后者不起作用。它说“Something”不存在。这个修改过的版本虽然有效,但仍然不直观,不需要也不会接受“typename”。

template < typename T > struct wtf { typedef typename T::what type; };

template < typename Something >
boost::function<void()> f()
{
  return []() { typedef wtf<Something>::type type; };
}

当然,现在我有两个问题:原版和WTF没有找到“Something”,除非它被用作模板参数??

2 个答案:

答案 0 :(得分:3)

这是一个非常有趣的问题。根据我的理解,根据N3225 5.1.2 / 7,第一个'WTF'(lambda体中typename的那个)应该是正确的:

  

lambda-expression 复合语句产生函数调用运算符的 function-body ,   但出于名称查找的目的,确定此类型和值以及转换 id-expressions   使用(* this)将非静态类成员引用到类成员访问表达式中,    复合语句 lambda-expression 的上下文中被考虑。

由于Something是lambda表达式上下文中的依赖名称,因此根据此引用,应该是lambda函数体上下文中的依赖名称。< / p>

答案 1 :(得分:0)

这是因为lambda实际上是由编译器定义的类,它不共享外部函数的模板参数,在实例化模板时定义了lambda类型,因此模板参数不再依赖于{{ 1}}不需要。