You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用`operator=`时自动传入`const stsb::promise<int>`类型的`this`?

问题分析与解决:promise类赋值时的const限定错误

问题代码

主程序代码

#include "promise.hpp"
#include <thread>
using namespace std;
int main() {
    stsb::promise<int> tstint = stsb::promise<int>();
    thread waitthr = thread([tstint]() {
       // do some work
       tstint = 27;
    });
    waitthr.detach();
    // wait for result and do smth with it
}

stsb::promise模板类代码

#include <mutex>
#include <optional>
#include <memory>

namespace stsb {
    template<typename T>
    class promise {
    private:
        std::shared_ptr<T> storage;
        std::shared_ptr<bool> ready;
        std::mutex mtx;
    public:
        inline promise(T& storage) : storage(std::make_shared<T>(storage)), ready(new bool(false)), mtx() {}
        inline promise(void) : storage(new T()), ready(new bool(false)), mtx() {}
        inline promise(const promise& cp) : storage(cp.storage), ready(cp.ready), mtx() {}
        inline promise(promise&& cp) : storage(cp.storage), ready(cp.ready), mtx() {}
        inline promise<T>& operator=(T&& value) { mtx.lock(); *(storage.get()) = value; mtx.unlock(); *(ready.get()) = true; return *this; }
        inline std::optional<T> operator()() { mtx.lock(); if (!(*(ready.get()))) { mtx.unlock(); return std::nullopt; } auto tmp = *(storage.get()); mtx.unlock(); return tmp; }
        inline ~promise() {}
    };
}

错误信息

error: passing 'const stsb::promise<int>' as 'this' argument discards qualifiers [-fpermissive]

错误出现在tstint = 27;这一行。

错误原因

默认情况下,lambda表达式的operator()是const成员函数,按值捕获的tstint在lambda内部会被视为const对象。而你的promise<T>::operator=(T&&)是非const成员函数,C++不允许在const对象上调用非const成员函数,因此触发了这个错误。

解决方案

1. 按引用捕获对象(推荐)

将lambda的捕获方式改为引用捕获,这样内部操作的就是原对象,而非const副本:

thread waitthr = thread([&tstint]() {
   // do some work
   tstint = 27;
});

注意:由于线程使用了detach(),必须保证main函数不会在线程执行完毕前退出,否则原对象tstint会被销毁,导致线程访问悬空引用。

2. 让lambda变为mutable(不推荐此场景)

如果坚持按值捕获,可以给lambda加上mutable修饰符,这样lambda的operator()会失去const限定,内部的tstint就可以被修改:

thread waitthr = thread([tstint]() mutable {
   // do some work
   tstint = 27;
});

但这种方式修改的是lambda内部的tstint副本,原对象不会被更新,完全不符合你用promise传递结果的需求,因此不建议使用。

3. 额外优化:修复promise类的mutex使用问题

你的promise类中直接调用mtx.lock()和mtx.unlock()存在风险——如果赋值过程中抛出异常,mutex会一直处于锁定状态,导致死锁。应该用RAII工具std::lock_guard自动管理锁的生命周期:

inline promise<T>& operator=(T&& value) {
    std::lock_guard<std::mutex> lock(mtx);
    *storage = std::move(value);
    *ready = true;
    return *this;
}

inline std::optional<T> operator()() {
    std::lock_guard<std::mutex> lock(mtx);
    if (!*ready) {
        return std::nullopt;
    }
    return *storage;
}

内容的提问来源于stack exchange,提问作者Stas Badzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:23:13