這里是一個簡化版的問題,是從大型代碼庫中移植過來的。我已經解決了這個問題,但我不喜歡我解決這個問題的方式。
不能編譯的問題代碼是這樣的,我從:
開始#include <iostream>
#include <cstdlib>
#include <vector>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <array>
#include <utility>
#include <set>
#include <functional>
class S {
public:
int a;
int b;
mutable int c。
void set_c() { c = 222; }; c = 222; }
};
結構 CMP
{
bool operator() const S& lhs, constS& rhs) const
{
return !(lhs.a == rhs.a && lhs.b == rhs.b) 。
};
class core {
public:
std::set<S, cmp> set_of_S;
std::function<void()> f;
void set_fn() {
f = [this]() {
auto it = set_of_S.begin();
it->set_c()。
};
}
};
int main()
{
core核心。
S a {.a = 2, .b = 3, .c = 0};
S b {.a = 2, .b = 3, .c = 0};
S c {.a = 2, .b = 4, .c = 0};
core.set_of_S.insert(a)。
core.set_of_S.insert(b)。
core.set_of_S.insert(c)。
core.set_fn()。
core.f()。
std::cout << core.set_of_S.size() << '
'。
編譯器的錯誤是:
prog.cc: In lambda function:
prog.cc:37:23: error: 傳遞'const S'作為'this'引數會拋棄限定詞 [-fpermissive]
it->set_c()。
好的,有道理。正如一些人告訴我的,你應該使用關鍵字mutable,因為this沒有被捕獲為const,迭代器it現在應該是可修改的(至少是我所期望的):
void set_fn(){
f = [this]() mutable{
auto it = set_of_S.begin();
it->set_c()。
};
}
這并不能編譯。這一部分對我來說沒有意義。所以一個成員函式不能在lambda內部修改捕獲的this,但是如果你試圖直接修改lambda內部的S::c,編譯器認為那是可以的。什么?對我來說沒有意義。
當我改變:
void set_c(){ c = 222; }
to
void set_c() const{ c = 222; }
它最終會被編譯,但我不喜歡這個解決方案,因為我們不得不修改原來的函式簽名,只是因為lambda不接受它,這使得它的可讀性降低。我認為lambdas是一種工具,而不是你必須針對它進行設計。我試著把mutable關鍵字放在所有的地方,但不能讓它編譯。我認為應該有一種方法來允許成員函式在 lambda 中修改它自己的狀態。
我是否遺漏了什么,還是說這是一個編譯器錯誤?
以下是wandbox中的問題代碼。https://wandbox.org/permlink/qzFMW6WIRiKyY3Dj
我知道這個問題已經被問到了。error: passing xxx as 'this' argument of xxx discards qualifiers but answers won't discuss on using mutable which to my understanding should solve these kind of situations.
uj5u.com熱心網友回復:
std::set<T>的元素是不可修改的 - set_of_S.begin()回傳一個常數迭代器。cppreference
因為iterator和const_iterator都是常數迭代器(事實上可能是同一型別),所以不可能通過這些成員函式[
begin/cbegin]回傳的迭代器來突變容器的元素。
這意味著迭代器it所指向的元素是const,所以你不能對它呼叫一個非const函式,如set_c。it->c = 300仍然有效,因為你已經使c變得可變。這與你呼叫的lambda是否可變沒有關系。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/306747.html
標籤:
