[英]std::function const correctness not followed
I was surprised to find this code compiles: 我惊讶地发现这段代码编译:
#include <functional>
struct Callable {
void operator() () { count++; }
void operator() () const = delete;
int count = 0;
};
int main() {
const Callable counter;
// counter(); //error: use of deleted function 'void Callable::operator()() const'
std::function<void(void)> f = counter;
f();
const auto cf = f;
cf();
}
https://wandbox.org/permlink/FH3PoiYewklxmiXl https://wandbox.org/permlink/FH3PoiYewklxmiXl
This will call the non-const call operator of Callable
. 这将调用
Callable
的非const调用操作符。 Comparatively, if you do const auto cf = counter; cf();
相比之下,如果你做
const auto cf = counter; cf();
const auto cf = counter; cf();
then it errors out as expected. 然后它按预期错误输出。 So, why does const correctness not seem to be followed with
std::function
? 那么,为什么const正确性似乎没有跟随
std::function
?
std::function
adds a layer of indirection, and this layer of indirection does not pass through const
ness to the callable. std::function
添加了一个间接层,这个间接层不会通过const
传递给callable。
I'm not really sure why this is — probably because std::function
takes a copy of the callable and has no need to keep the copy const
(in fact this might break assignment semantics) — I'm also not really sure why you'd need it to. 我不确定为什么会这样 - 可能是因为
std::function
需要一个可调用的副本而且不需要保留副本const
(实际上这可能会破坏赋值语义) - 我也不确定你为什么这么做我需要它。
(Of course, directly invoking operator()
on an object of a type that you just so happened to call Callable
and declared as const
will require a const
context, as it would with any other object.) (当然,直接在一个类型的对象上调用
operator()
,你恰好调用Callable
并声明为const
将需要一个const
上下文,就像对任何其他对象一样。)
Best practice is to give the callable a const
operator()
and leave it at that. 最佳实践是给callable一个
const
operator()
并保留它。
tl;dr: true, but not a bug, and doesn't matter tl; dr:是的,但不是一个bug,并不重要
You are correct to find this weird. 你发现这很奇怪是对的。 The call operator of
std::function
is marked const
but the const
ness is not propagated when the target object is actually invoked. std::function
的调用运算符标记为const
但实际调用目标对象时不会传播const
。 The proposal p0045r1 seems to remedy this by making the call operator of std::function
non-const but allowing the following syntax: 提议p0045r1似乎通过使
std::function
非const的调用运算符但允许以下语法来解决这个问题:
std::function<return_type(arg_type) const>
The reason is that assigning counter
to std::function
object creates a copy of counter
. 原因是为
std::function
对象分配counter
会创建一个counter
的副本。
In your case, f
is initialized using the following constructor: 在您的情况下,使用以下构造函数初始化
f
:
template< class F >
function( F f );
As described here , this constructor "initializes the target with std::move(f)" - a new object of type Callable
is created and initialized using copy constructor. 如上所述这里 ,这个构造“与标准::移动(F)初始化目标” -类型的新对象
Callable
创建和使用拷贝构造函数初始化。
If you'd like to initialize f
with a reference to counter
instead, you can use std::ref
: 如果您想使用对
counter
的引用来初始化f
,则可以使用std::ref
:
std::function<void()> f = std::ref(counter);
std::ref
returns an instance of std::reference_wrapper
, which has operator ()
, which calls Callable
's operator () const
. std::ref
返回一个std::reference_wrapper
的实例,它有operator ()
,它调用Callable
的operator () const
。 As expected, you'll get an error, since that operator is deleted. 正如预期的那样,您将收到错误,因为该运算符已被删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.