我试图理解为什么这个代码段失败了:
#include <iostream>
using namespace std;
template <typename Lambda>
struct Handler
{
bool _isCompleted;
bool isCompleted() { return _isCompleted; }
Lambda _l;
Handler(Lambda&& l) : _l(l) {}
void call() { _l(this); }
};
int main()
{
auto l1 = new Handler( [&](decltype(l1) obj )->
{
obj->_isCompleted = true;
cout << " is completed?" << obj->isCompleted() << endl;
});
l1->call();
};
g ++ 4.5失败了:
test.cpp: In function ‘int main()’:
test.cpp:21:17: error: expected type-specifier before ‘Handler’
test.cpp:21:17: error: expected ‘,’ or ‘;’ before ‘Handler’
test.cpp:25:2: error: expected primary-expression before ‘)’ token
test.cpp:25:2: error: expected ‘;’ before ‘)’ token
test.cpp:26:7: error: request for member ‘call’ in ‘* l1’, which is of non-class type ‘int’
我的理解是auto l1
应解析为Handler<lambdaType>*
,lambdaType应具有公共函数签名void( Handler<LambdaType>*)
。我没有看到上面的例子有任何明显的错误(你知道,除了lambda和处理程序类型之间的丑陋和轻微的病态循环依赖)
答案 0 :(得分:5)
正如@Cat所说,一个问题是模板参数推导不适用于构造函数调用。您始终需要指定模板参数。
Clang使用以下代码段很好地说明了另一个问题:
struct X{
X(...){}
};
int main(){
auto l = X([](decltype(l)& o){});
}
输出:
t.cpp:6:26: error: variable 'l' declared with 'auto' type cannot appear in its
own initializer
auto l = X([](decltype(l)& o){});
^
1 error generated.
强制性标准报价:
§7.1.6.4 [dcl.spec.auto] p3
否则,变量的类型是从其初始化程序推导出来的。声明的变量的名称不应出现在初始化表达式中。 [...]
答案 1 :(得分:2)
类型推导不适用于构造函数。 auto
将推断出表达式的类型,是的,但new Handler()
需要显式类型。写一个工厂函数:
// also don't use raw owning pointers
template <typename L>
std::unique_ptr<Handler<L>> make_handler(L lambda) {
return std::unique_ptr<Handler<L>>(new Handler<L>(lambda));
}
当然,它重复了一下,但只有一次。然后就可以了
auto l1 = make_handler([](...) { ... });
auto l2 = make_handler([](...) { ... });
它会正常工作。