【问题标题】:Change return value, without function overload改变返回值,没有函数重载
【发布时间】:2022-01-11 18:44:33
【问题描述】:

我有一个关于 boos::function 的问题。我有一个带有 boost::function 作为参数的函数。这个 boost::function 的返回值是 void()。但是我在代码中调用了函数 ChangeWorking(...) 几次,在一种情况下,我需要 boost::function 的返回值。有人知道如何解决这个问题吗?

实际功能如下:

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
}

但我还需要一个函数,看起来像这样(这个函数没有实现):

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
}

这可能吗,还是我必须编写一个新函数?

【问题讨论】:

  • 你不能返回一个值并忽略它吗?
  • 没有。如果我从每个函数返回一个值,我必须多次更改代码。
  • 那我不明白这个问题。您不能从返回类型为 void 的函数返回某些内容
  • 这已经是两个不同的函数了,因为参数的类型不同。不知道pWork从哪里来,没什么好说的。
  • 您可以在function 中存储一个 lambda,该 lambda 封装了一些函数调用以及可能的返回值处理。比如:godbolt.org/z/G6x6bqdMf.

标签: c++ boost


【解决方案1】:

一开始我可能不会硬编码function&lt;&gt;。使用一些 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;
    });
}

打印例如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

【讨论】:

    【解决方案2】:

    能不能把a_pFunc(假设是shared_ptr)的类型改成boost::function&lt;void( std::shared_ptr&lt;CPamWorking&gt;&amp;)&gt; a_pFunc,这样你就可以决定是否改变你在a_pFunc的实现中传递过来的p_worker

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多