使用模板参数推导将lambda存储为成员
Store lambda as a member using template arguments deduction
以前,当 c++ 11可用时,我尝试使用auto
说明符和成员初始化式将lambda存储为类字段。这是一次不成功的尝试:
struct Y
{
auto x = [] { ; };
};
错误:错误:用占位符'auto'声明非静态数据成员
尽管在定义类成员时已知lambda的大小(w/o丧失了捕获的通用性),但不允许使用auto
指示符。为什么?限制不太明确
现在可以在GCC 7.0.0 trunk中使用类模板的模板参数推导。我试着再做一次:
template< typename F >
struct X
: F
{
using F::operator ();
X(F && f) : F(static_cast< F && >(f)) { ; }
};
struct Y
{
X x = [] { ; };
};
但是我得到一个错误:
错误:无效使用模板名'X'没有参数列表
我怀疑,实现是部分的,甚至可能不一致。它是否允许我实现所需的w/o类型擦除(和内存的动态分配)?
允许自由的非成员定义:
X x = [] { ; };
附加:
人们问我试图解决什么问题?对于类内定义的函子,我需要一个简洁的语法。
如果我能写(下面的代码是有效的):
struct point_of_parabaloid // aggregate
{
double x, y;
double z = [&] { return x * x + y * y; }();
};
point_of_parabaloid p = {1.0, 2.0};
assert(p.z == 5.0);
为什么我不能定义一个类内lambda(说,为z
的惰性评估)?
我不需要捕获异常的东西,只是一个类成员(或this
)在point_of_parabaloid
定义
如果lambda事先已知,则可以使用decltype
解决此问题:
auto lambda = [](){};
struct C {
decltype(lambda) member = lambda;
};
不是很漂亮,但是很好用。
我认为你的模板技术可以工作,如果重写为:
auto x = X([](){});
但是gcc-7 (snapshot)也不接受。我怀疑这是因为它仍在进行中。
[刚刚在20161014上构建的g++ 7主干上再次测试,然后上述工作]
你可以使用maker函数
来解决这个问题template <typename L>
struct X {
L member;
};
template <typename T>
auto make_x(T t) { return X<T>{t}; }
auto x = make_x([](){});
您的问题是您试图在类定义中捕获成员函数之外的this
。确切地说,double z = [&] { return x * x + y * y; }();
需要this->x
和this->y
。
你现在进入了一个循环依赖:lambda的类型取决于捕获的内容(this
,这是point_of_parabaloid*
),但point_of_parabaloid
取决于其成员的类型,包括那个lambda。
在你的设计中这是一个循环依赖;确切的c++结构并不重要。你可以打破它;point_of_parabaloid*
只需要前向声明struct point_of_parabaloid;
。但是打破这个循环并不能让你得到简洁的语法
看看你在c++ 17中的尝试,你已经可以在c++ 11中做类似的事情了。
例如:
#include<utility>
template<typename F>
struct S {
S(F f): f{f} {}
F f;
};
template<typename F>
struct T: F {
T(F f): F{f} {}
};
int main() {
auto l = [](){ ; };
S<decltype(l)> s{l};
s.f();
T<decltype(l)> t{l};
t();
}
如果需要,可以将丑陋的decltype
隐藏在工厂方法后面:
template<typename L>
static auto create(L l) {
return S<decltype(l)>{l};
}
关于这个的限制:
struct Y { auto x = [] { ; }; };
不是因为lambda。相反,这是因为auto
占位符。根据标准,它不能用于声明非静态数据成员。
我猜原因是静态数据成员的类型在编译时就知道了(迟早必须放入唯一的定义),而非静态数据成员的类型可能需要在运行时解决。例如,想象一个if/else
语句,其中使用两个不同的lambda来初始化对象。
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- C++:对象将 lambda 存储到结构中,稍后调用该函数
- 是否可以将具有不同签名的 lambda 存储在 std::vector 中并在函数中执行它们(使用各自的参数)?
- 可以将模板化的 lambda 存储到 std::function 中吗?
- 将 lambda 存储为 std::函数时出现分段错误
- 在不模板化类的情况下存储 lambda
- 存储可变参数模板参数并将其传递给 lambda
- (C )将lambda函数存储在Boost Multi_Array中
- 带有动态存储持续时间的lambda
- Python -> C++ 习语:将 lambda 表达式存储在映射/容器中
- 存储lambda函数,该函数将范围变量捕获为类成员以供重用
- lambda 捕获的变量存储在哪里
- 将多种类型的 lambda 函数存储在一种类型的变量中
- C++ 存储在容器捕获"this"中的 Lambda
- 存储在std::函数中时,无法将无捕获lambda转换为函数指针
- 为什么我不能在SERVICE_TABLE_ENTRY中存储 lambda 函数?
- 如何在C++11中将lambda表达式存储为类的字段
- 将Lambda存储在类中
- 如何使c++ lambda对象的存储更高效?
- 使用模板参数推导将lambda存储为成员