[英]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 ()
,它調用Callable
的operator () const
。 正如預期的那樣,您將收到錯誤,因為該運算符已被刪除。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.