门吹西风 2024-08-21 17:43 采纳率: 25%
浏览 3

如下C++代码,被注释的部分编译不过

#include <iostream>
#include <memory>
#include <functional>

class OperationGuard final {
public:
    template<typename Func, typename... Args>
    OperationGuard(Func func, Args&&... args)
        :functor_(std::bind(std::move(func), std::forward<Args>(args)...))
    {
    }

    void releaseControl(bool releaseCondition = true)
    {
        control_ = !releaseCondition;
    }

    OperationGuard& operator=(OperationGuard&&) = delete;
    OperationGuard(OperationGuard&& rhs): functor_(std::move(rhs.functor_))
    {
        control_ = rhs.control_;
        rhs.control_ = false;
    }

    ~OperationGuard() noexcept
    {
        if (control_) {
            try {
                functor_();
            } catch (...) {
            }
        }
    }
private:
    std::function<void()> functor_;
    bool control_ = true;
};

void testFunc(int x, int y) {
    std::cout << "func1: " << x + y << std::endl;
}

void testPtrFunc(std::unique_ptr<int> param)
{
    if (param.get() != nullptr) {
        std::cout << "testGlobalPtrFunc: param=" << * param << std::endl;
    }
}

int main()
{
    {
        OperationGuard opGuard(&testFunc, 1, 2);    
    }  
    // {
    //     std::unique_ptr<int> param = std::make_unique<int>(10);
    //     OperationGuard opGuard(&testPtrFunc, std::move(param));    
    // }

    return 0;
}

搜了下发现std::function不支持std::unique_ptr类型的参数,原因是std::unique_ptr的拷贝构造给禁用了。有啥好办法解决?
https://stackoverflow.com/questions/20268482/binding-functions-with-unique-ptr-arguments-to-stdfunctionvoid
https://stackoverflow.com/questions/8640393/move-capture-in-lambda/20669290#20669290

  • 写回答

1条回答 默认 最新

  • 吃不了席 2024-08-21 17:44
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    为了解决这个问题,你可以使用std::reference_wrapper来包装std::unique_ptr,这样你就可以将其传递给std::function。以下是修改后的代码:

    #include <iostream>
    #include <memory>
    #include <functional>
    
    class OperationGuard final {
    public:
        template<typename Func, typename... Args>
        OperationGuard(Func func, Args&&... args)
            :functor_(std::bind(std::move(func), std::forward<Args>(args)...))
        {
        }
    
        void releaseControl(bool releaseCondition = true)
        {
            control_ = !releaseCondition;
        }
    
        OperationGuard& operator=(OperationGuard&&) = delete;
        OperationGuard(OperationGuard&& rhs): functor_(std::move(rhs.functor_))
        {
            control_ = rhs.control_;
            rhs.control_ = false;
        }
    
        ~OperationGuard() noexcept
        {
            if (control_) {
                try {
                    functor_();
                } catch (...) {
                }
            }
        }
    private:
        std::function<void()> functor_;
        bool control_ = true;
    };
    
    void testFunc(int x, int y) {
        std::cout << "func1: " << x + y << std::endl;
    }
    
    void testPtrFunc(std::unique_ptr<int>& param)
    {
        if (param.get() != nullptr) {
            std::cout << "testGlobalPtrFunc: param=" << * param << std::endl;
        }
    }
    
    int main()
    {
        {
            OperationGuard opGuard(&testFunc, 1, 2);    
        }  
        {
            std::unique_ptr<int> param = std::make_unique<int>(10);
            OperationGuard opGuard(&testPtrFunc, std::ref(param));    
        }
    
        return 0;
    }
    

    在这个修改后的代码中,我们将testPtrFunc的参数类型更改为std::unique_ptr<int>&,然后在调用OperationGuard时使用std::ref来传递param的引用。这样,std::function就可以正确地捕获并存储对std::unique_ptr的引用,而不是尝试复制它。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月21日