繁体   English   中英

没有遵循std :: function const的正确性

[英]std::function const correctness not followed

我惊讶地发现这段代码编译:

#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

这将调用Callable的非const调用操作符。 相比之下,如果你做const auto cf = counter; cf(); const auto cf = counter; cf(); 然后它按预期错误输出。 那么,为什么const正确性似乎没有跟随std::function

std::function添加了一个间接层,这个间接层不会通过const传递给callable。

我不确定为什么会这样 - 可能是因为std::function需要一个可调用的副本而且不需要保留副本const (实际上这可能会破坏赋值语义) - 我也不确定你为什么这么做我需要它。

(当然,直接在一个类型的对象上调用operator() ,你恰好调用Callable并声明为const将需要一个const上下文,就像对任何其他对象一样。)

最佳实践是给callable一个const operator()并保留它。

tl; dr:是的,但不是一个bug,并不重要

你发现这很奇怪是对的。 std::function的调用运算符标记为const但实际调用目标对象时不会传播const 提议p0045r1似乎通过使std::function非const的调用运算符但允许以下语法来解决这个问题:

std::function<return_type(arg_type) const>

原因是为std::function对象分配counter会创建一个counter的副本。

在您的情况下,使用以下构造函数初始化f

template< class F >
function( F f );

如上所述这里 ,这个构造“与标准::移动(F)初始化目标” -类型的新对象Callable创建和使用拷贝构造函数初始化。

如果您想使用对counter的引用来初始化f ,则可以使用std::ref

std::function<void()> f = std::ref(counter);

std::ref返回一个std::reference_wrapper的实例,它有operator () ,它调用Callableoperator () const 正如预期的那样,您将收到错误,因为该运算符已被删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM