在另一个 lambda 中捕获一个 lambda 可能会违反 const 限定符
Capturing a lambda in another lambda can violate const qualifiers
请考虑以下代码:
int x = 3;
auto f1 = [x]() mutable
{
return x++;
};
auto f2 = [f1]()
{
return f1();
};
这不会编译,因为f1()
不是常量,并且f2
不会声明为可变的。这是否意味着如果我有一个接受任意函数参数并将其捕获在 lambda 中的库函数,我总是需要使该 lambda 可变,因为我不知道用户可以传入什么?值得注意的是,将f1
包装在std::function
中似乎可以解决此问题(如何?
这是否意味着如果我有一个接受任意函数参数并将其捕获在 lambda 中的库函数,我总是需要使该 lambda 可变,因为我不知道用户可以传入什么?
这是库 API 的设计决策。您可以要求客户端代码使用限定const
operator()
传递函数对象(非mutable
lambda 表达式就是这种情况)。如果传递了不同的内容,则会触发编译器错误。但是,如果上下文可能需要修改其状态的函数对象参数,那么是的,您必须使内部 lambdamutable
。
另一种方法是调度在给定函数类型的const
限定实例上调用operator()
的能力。类似这些内容(请注意,这需要修复同时具有const
和非const
operator()
的函数对象,这会导致歧义):
template <class Fct>
auto wrap(Fct&& f) -> decltype(f(), void())
{
[fct = std::forward<Fct>(f)]() mutable { fct(); }();
}
template <class Fct>
auto wrap(Fct&& f) -> decltype(std::declval<const Fct&>()(), void())
{
[fct = std::forward<Fct>(f)]() { fct(); }();
}
值得注意的是,将 f1 包装在 std::function 中似乎可以解决这个问题(如何?
这是std::function
中的一个错误,因为它的类型擦除和复制语义。它允许调用非const
限定operator()
,可以使用以下代码片段进行验证:
const std::function<void()> f = [i = 0]() mutable { ++i; };
f(); // Shouldn't be possible, but unfortunately, it is
这是一个已知问题,值得查看Titus Winter对此的投诉。
我将首先解决您的第二个问题。std::function
类型擦除,并保存初始化它的函子的副本。这意味着std::function::operator()
和实际函子的operator()
之间有一层间接性。
如果你愿意的话,想象一下,在你的课堂上通过指针持有一些东西。然后,您可以从类的 const 成员函数调用对 pointee 的变异操作,因为它不会影响(在浅视图中)类持有的指针。这与你观察到的情况类似。
至于你的第一个问题..."总是"这个词太强烈了。这取决于你的目标。
-
如果你想轻松支持自变异函子,那么你应该捕获一个可变的 lambda。但请注意,它可能会影响您现在可以调用的库函数。
-
如果您希望支持非可变操作,那么使用不可变的 lambda。我之所以说"青睐",是因为正如我们所观察到的,类型系统可以通过额外的间接性来"愚弄"。因此,您喜欢的方法只会更容易使用,而不是不可能。正如圣人的建议所说,正确使用您的 API 变得容易,不正确更难。
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- std::move a const std::vector in a lambda capture
- C++ 一个lambda浅拷贝const Type&如果它被赋予一个命名捕获,如[copy=val](){}?
- 我应该使用 const shared_ptr<T>&or shared_ptr<T> 作为我的 lambda 函数的参数吗?
- 在lambda中捕获各种向量使元素const
- const std::unordered_map<char, int>' 因为 'this' 参数会丢弃 lambda 中的限定符
- 我需要用c ++ 98重写c ++ 11代码,c ++ 11正在使用lambda函数[&](const Output & o
- lambda捕获的const int变量的值类别
- 在另一个 lambda 中捕获一个 lambda 可能会违反 const 限定符
- 不可变的 lambda 函数:复制捕获的变量是否允许是 const
- const std::function 包装一个非 const 运算符() / 可变 lambda
- 在 lambda 闭包中复制的 const 对象不可变
- 所有lambda声明都应该是const-static
- 从lambda返回局部变量到const ref
- Lambda:为什么是通过值const捕获,而不是通过引用值捕获
- 将非const引用使用auto-keyword声明的lambda作为实参传递给std::函数形参类型
- G++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?
- 在参数列表中没有"const"的情况下无法编译 lambda
- 按值可变的 lambda 捕获不适用于 const &?
- Lambda:应该逐引用捕获const引用,从而产生未定义的行为