考虑:
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”,除非它被用作模板参数??
答案 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}}不需要。