std :: bind vs std :: shared_ptr

时间:2014-02-24 10:34:30

标签: c++ c++11 bind std shared-ptr

无法理解如何使用shared_ptr绑定到类函数。 USE 行发生错误,因为编译器无法将 shared_ptr 转换为 A

#include <functional>

class A {
    public:
        const bool check(void) const { return true; };
};

int _tmain(int argc, _TCHAR* argv[]) {
    const std::function<const bool(const A)> f_check = &A::check;
    auto a = std::make_shared<const A>();
    auto f_check_a = std::bind(f_check, a); // line BIND
    auto res = f_check_a(); // line USE - ERROR!!!

    return 0;
}

我可以替换 BIND 行来访问智能指针的实际值:

int _tmain(int argc, _TCHAR* argv[]) {
    auto f_check = &A::check;
    auto a = std::make_shared<const A>();
    auto f_check_a = std::bind(f_check, *a.get()); // line BIND
    auto res = f_check_a(); // line USE - NO ERRORS

    return 0;
}

现在编译代码,可能会有效。 但我想知道 - 从智能指针使用原始值是否可以接受?我可以以某种方式使用shared_ptr而不是原始值吗?

UPD2: 看起来我的同事找到了一个很好的解决方法:

class A {
    public:
        const bool check(void) const { return true; };
};

using p_func = const bool(A::*)() const;

int _tmain(int argc, _TCHAR* argv[]) {
    auto a = std::make_shared<const A>();
    p_func b = &A::check;
    auto f_check_a = std::bind(b, a);
    auto res = f_check_a();
}

现在我可以发送b作为参数并绑定到 shared_ptr

UPD: 我不能在我的真实任务中使用lambda。 以下是来自实际项目的更多代码:

#include <functional>
#include <algorithm>

class Block {
    public:
        const bool check1(void) const { return false; };
        const bool check2(void) const { return false; };
        const bool check3(void) const { return false; };
};

using block_t = std::shared_ptr<const Block>;

class Worker {
    private:
        std::vector<const block_t> _container;
    public:
        void processor(const std::function<const bool(const Block)> f_check) {
            block_t my_block = nullptr;
            auto lambda = [my_block, f_check](const block_t block) mutable {
                auto function_check = std::bind(f_check, *block.get());
                if (function_check()) {
                    my_block = block;
                    return true;
                }
                return false;
            };
            std::find_if(_container.begin(), _container.end(), lambda);
        }
};

void test(block_t block) {
    Worker worker;
    worker.processor(&Block::check1);
    worker.processor(&Block::check2);
    worker.processor(&Block::check3);
}

UPD3: 修复了没有智能指针解除引用的代码:

#include <functional>
#include <algorithm>

class Block {
public:
    const bool check1(void) const { return false; };
    const bool check2(void) const { return false; };
    const bool check3(void) const { return false; };
};

using block_t = std::shared_ptr<const Block>;
using p_func = const bool(Block::*)() const;

class Worker {
private:
    std::vector<const block_t> _container;
public:
    void processor(p_func f_check) {
        block_t my_block = nullptr;
        auto lambda = [my_block, f_check](const block_t block) mutable {
            auto function_check = std::bind(f_check, block);
            if (function_check()) {
                my_block = block;
                return true;
            }
            return false;
        };
        std::find_if(_container.begin(), _container.end(), lambda);
    }
};

void test(block_t block) {
    Worker worker;
    worker.processor(&Block::check1);
    worker.processor(&Block::check2);
    worker.processor(&Block::check3);
}

4 个答案:

答案 0 :(得分:3)

您的问题是您首先从成员函数创建std::function,期望A实例,而不是尝试将其绑定到shared_ptr。您可以跳过该部分:

auto a = std::make_shared<const A>();
auto f_check_a = std::bind(&A::check, a);
auto res = f_check_a(); 

std::bind知道如何将成员函数直接绑定到shared_ptr

答案 1 :(得分:2)

您必须使用std::bind吗?你可以改用lambda。

auto f_check_a = [=]{ return a->check(); };

答案 2 :(得分:1)

function期望获得A的实例,而不是shared_ptr<A>,所以我相信你问题的答案基本上是肯定的。

但是,我会对您的代码进行2次更改,如下所示(请参阅我的评论):

const std::function<const bool(const A&)> f_check = &A::check; // <-- Added & after A here
auto a = std::make_shared<const A>();
auto f_check_a = std::bind(f_check, *a); // <-- no need to call get() on a
auto res = f_check_a(); // line USE - ERROR!!!

答案 3 :(得分:1)

  

但我想知道 - 从智能指针使用原始值是否可以接受?

是的,但你可以写*a代替*a.get()

但是,从bind返回的调用包装器具有对A对象的引用,因此您有责任确保引用保持有效。如果绑定shared_ptr那么会增加引用计数并使对象保持活动状态。

  

我可以以某种方式使用shared_ptr而不是原始值吗?

如果您使用std::function<const bool(const A)>,则无法传递shared_ptr<const A>

当您使用std::function<const bool(const A)>时,您创建了一个具有完全呼叫签名const bool(const A)的可调用类型,因此您必须向其传递一个可转换为const A的参数,并{{1 }}无法转换为shared_ptr<const A>

解决方法是使用lambda来合并const Astd::function

shared_ptr

但是,您正在尝试解决不应存在的问题,只需执行此操作:

            auto function_check = [] { return f_check(*block); };
            if (function_check()) {

然后你不需要 if (f_check(*block)) { my_block = block; return true; } return false; 任何东西。