簡體   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