Home > OS >  Change return value, without function overload
Change return value, without function overload

Time:12-07

I have a question about boos::function. I have a function with a boost::function as a parameter. This boost::function has the return value void(). But I call the function ChangeWorking(...) couple times in my code and for one case I need a return value from the boost::function. Has anybody an idea how to solve that problem?

The actual function looks like this:

void CElmWorkingPropertyList::ChangeWorking( boost::function<void( CPamWorking* )> a_pFunc, bool a_bAlignmentChange )
{
    //do some stuff
    CPamWorkingPtr pWork = IsBlockEditActive() ? pWorkSource : pWorkSource->Clone();

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

    if (a_pFunc)
    {
        a_pFunc(pWork.get());
    }
    //do more stuff
}

But I need also a function, which look like this (This function is not implemented):

void CElmWorkingPropertyList::ChangeWorking( boost::function<CPamWorking*( CPamWorking* )> a_pFunc, bool a_bAlignmentChange )
{
     //do same stuff
    if (a_pFunc)
    {
        pWork = a_pFunc(pWork.get());
    }
    //do more same stuff
}

Is that possible or do I have to write a new function?

CodePudding user response:

Can you change the type of a_pFunc(Assumed to be a shared_ptr) to boost::function<void( std::shared_ptr<CPamWorking>&)> a_pFunc, so that you can decide whether to change the p_worker you passed by in the implementation of a_pFunc?

CodePudding user response:

I would probably not hardcode function<> in the first place. With some C 17:

Live On Coliru

#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <type_traits>

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>();
    }
};

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

    template <typename Func>
    void ChangeWorking(
        Func a_pFunc = [](CPamWorkingPtr) {}, 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());

            bool constexpr returns_work =
                std::is_assignable_v<CPamWorkingPtr, decltype(a_pFunc(pWork))>;

            if constexpr (returns_work) {
                std::cout << "DEBUG: setting returned work\n";
                pWork = a_pFunc(pWork);
            } else {
                std::cout << "DEBUG: no returned work\n";
                a_pFunc(pWork);
                break;
            }
        }
    }

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

int main() {
    CElmWorkingPropertyList wpl;
    wpl.ChangeWorking(
        [](CPamWorkingPtr w) { std::cout << "void work with " << w.get() << "\n"; });

    unsigned counter = 10;
    wpl.ChangeWorking([&counter](CPamWorkingPtr w) {
        std::cout << "non-void work with " << w.get() << "\n";
        return counter-- ? w->Clone() : nullptr;
    });
}

Prints eg Live On Coliru

DEBUG: no returned work
void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0ecc0
DEBUG: setting returned work
non-void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0ecc0
DEBUG: setting returned work
non-void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0ecc0
DEBUG: setting returned work
non-void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0ecc0
DEBUG: setting returned work
non-void work with 0xe0dc70
DEBUG: setting returned work
non-void work with 0xe0ecc0
DEBUG: setting returned work
non-void work with 0xe0dc70
  • Related