【问题标题】:Two boost::functions in boost::variantboost::variant 中的两个 boost::functions
【发布时间】:2022-01-12 07:02:11
【问题描述】:

这种函数是否可行,如果可以,我该如何调用a_pFunc?

void CElmWorkingPropertyList::ChangeWorking( boost::variant< boost::function<CPamWorkingPtr(CPamWorking*)>, boost::function<void( CPamWorking* )>>  a_pFunc, bool a_bAlignmentChange )

    if ( a_pFuncContainer.type() == typeid(CPamWorkingPtr))
    {
        pWork = boost::get<CPamWorkingPtr>(a_pFuncContainer);
    }
    else
    {
        boost::get<void>(a_pFuncContainer);
    }
    

【问题讨论】:

  • 它们是不同的类型,所以是的,它将与任何其他变体一样工作

标签: c++ boost


【解决方案1】:

这是my answer from yesterday 写在这个 - 严格来说更复杂 - 风格:

Live On Coliru

#include <boost/function.hpp>
#include <boost/variant.hpp>
#include <cassert>
#include <iostream>
#include <memory>

struct CComponent {
    virtual ~CComponent() = default;
};

using CPamWorkingPtr = std::shared_ptr<struct CPamWorking>;

struct CPamWorking : public std::enable_shared_from_this<CPamWorking> {
    virtual ~CPamWorking()         = default;
    virtual CPamWorkingPtr Clone() = 0;

    CComponent const* SetComponent(CComponent const* cc) { return std::exchange(m_component, cc); }
    CComponent const* GetComponent() const { return m_component; }

  private:
    CComponent const* m_component = nullptr;
};

struct ConcretePamWorking : CPamWorking {
    virtual CPamWorkingPtr Clone() override {
        return std::make_shared<ConcretePamWorking>();
    }
};

using VoidFunc = boost::function<void(CPamWorking*)>;
using WorkFunc = boost::function<CPamWorkingPtr(CPamWorking*)>;
using Func     = boost::variant<VoidFunc, WorkFunc>;

struct CElmWorkingPropertyList {
    bool IsBlockEditActive() const { return false; }

    void ChangeWorking(Func a_pFunc = {}, bool a_bAlignmentChange = false)
    {
        for (CPamWorkingPtr pWork = IsBlockEditActive() && pWorkSource
                 ? pWorkSource
                 : pWorkSource->Clone();
             pWork;) {

            if (!pWork) {
                assert(false); // current working needs to be there
                continue;
            }
            pWork->SetComponent(pWorkSource->GetComponent());

            struct invoker {
                CPamWorkingPtr& pWorkref;

                bool operator()(VoidFunc const& vf) const {
                    std::cout << "DEBUG: no returned work\n";
                    vf(pWorkref.get());
                    return true; // alternatively `pWorkref.reset()`?
                }
                bool operator()(WorkFunc const& wf) const {
                    std::cout << "DEBUG: setting returned work\n";
                    pWorkref = wf(pWorkref.get());
                    return false;
                }
            } invoke_helper {pWork};

            if (boost::apply_visitor(invoke_helper, a_pFunc))
                break;
        }
    }

  private:
    CPamWorkingPtr pWorkSource = std::make_shared<ConcretePamWorking>();
};

int main() {
    VoidFunc voidf = [](CPamWorking* w) { std::cout << "void work with " << w << "\n"; };
    unsigned counter = 10;
    WorkFunc chain   = [&counter](CPamWorking* w) {
        std::cout << "non-void work with " << w << "\n";
        return counter-- ? w->Clone() : nullptr;
    };

    CElmWorkingPropertyList wpl;
    wpl.ChangeWorking(voidf);
    wpl.ChangeWorking(chain);
}

打印例如

DEBUG: no returned work
void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc8acc0
DEBUG: setting returned work
non-void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc8acc0
DEBUG: setting returned work
non-void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc8acc0
DEBUG: setting returned work
non-void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc8acc0
DEBUG: setting returned work
non-void work with 0xc89c70
DEBUG: setting returned work
non-void work with 0xc8acc0
DEBUG: setting returned work
non-void work with 0xc89c70

你会明白我为什么推荐the more generic approach

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多