使用函数指针前向声明作为lamba声明

时间:2018-09-27 17:08:22

标签: c++ c++11

我最接近这样的东西吗?

.h:
    typedef bool (*DoWorkFunc)(uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2);
    void DoWork(DoWorkFunc func);

.cpp:
    bool MyClass::MyFunc(uint32_t val) {
        DoWork(DoWorkFunc { return c2.mVal < c1.mVal + fParam1 + fParam2; } );

        auto f1 = DoWorkFunc { return (bParam ? dParam1 : c1.mVal) < mVal; };
        auto f2 = DoWorkFunc { return ((dParam1 & dParam2) == 0) == bParam; };

        auto f = val < 3 ? f1: f2;
        DoWork(f);
    }

这是我所能获得的最接近的干净解决方案,它需要一个主要复制粘贴的lambda前向声明解决方案。

.h:
    typedef bool (*DoWorkFunc)(uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2);
    #define DoWorkLambda [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
    void DoWork(DoWorkFunc func);

.cpp:
    bool MyClass::MyFunc(uint32_t val) {
        DoWork(DoWorkLambda { return c2.mVal < c1.mVal + fParam1 + fParam2; } );

        auto f1 = DoWorkLambda { return (bParam ? dParam1 : c1.mVal) < mVal; };
        auto f2 = DoWorkLambda { return ((dParam1 & dParam2) == 0) == bParam; };

        auto f = val < 3 ? f1: f2;
        DoWork(f);
    }

这对于一次性解决方案还可以,但是最终却为多个函数声明提供了一个凌乱的标题

.h:

    typedef bool (*DoWorkFunc1)(uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2);
    #define DoWorkLambda1 [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
    void DoWork1(DoWorkFunc1 func);

    typedef bool (*DoWorkFunc2)(uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass3& c2);
    #define DoWorkLambda2 [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass3& c2) -> bool
    void DoWork2(DoWorkFunc2 func);

    ...

作为参考,这是没有预处理器的代码的样子:

.h:
    typedef bool (*DoWorkFunc)(uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2);
    void DoWork(DoWorkFunc func);

.cpp:
    bool MyClass::MyFunc(uint32_t val) {
        DoWork([](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
            {
                return c2.mVal < c1.mVal + fParam1 + fParam2;
            }
        );

        auto f1 = [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
        {
            return (bParam ? dParam1 : c1.mVal) < mVal;
        };
        auto f2 = [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
        {
            return ((dParam1 & dParam2) == 0) == bParam;
        };

        auto f = val < 3 ? f1: f2;
        DoWork(f);
    }

2 个答案:

答案 0 :(得分:0)

应该可以将lambda函数分配给等效的原始函数指针,但只有在不使用范围参数的情况下,即lambda声明中的方括号必须为空。

因此,您应该能够声明函数类型。使用语法最简单:

using DoWorkFnType =bool (uint32_t , uint32_t , bool , float , float , MyClass& , MyClass2& );
void DoWork(DoWorkFnType* fn);

bool MyClass::MyFunc(uint32_t val) {
    DoWorkFnType* f1 = [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
    {
        return (bParam ? dParam1 : c1.mVal) < mVal;
    };
    DoWorkFnType* f2 = [](uint32_t dParam1, uint32_t dParam2, bool bParam, float fParam1, float fParam2, MyClass& c1, MyClass2& c2) -> bool
    {
        return ((dParam1 & dParam2) == 0) == bParam;
    };

    auto f = val < 3 ? f1: f2;
    DoWork(f);
}

void DoWork(DoWorkFnType* fn)
{
  bool res= fn(arg1,arg2,arg3,arg4,arg5.arg6,arg7);
}

如果您的lambda使用本地范围,则只有std :: function才能将lambda传递给子函数。

从您的代码中根本不清楚您希望DoWork做什么,或者它如何收集调用f所需的7个参数值,所以我将需要保留它。

答案 1 :(得分:0)

.h:

struct DoWorkParams {
  uint32_t dParam1;
  uint32_t dParam2;
  bool bParam;
  float fParam1;
  float fParam2;
  MyClass& c1;
  MyClass2& c2;
};
typedef bool (*DoWorkFunc)(DoWorkParams);
void DoWork(DoWorkFunc func);

.cpp:

bool MyClass::MyFunc(uint32_t val) {
    DoWork([](auto p) { return p.c2.mVal < p.c1.mVal + p.fParam1 + p.fParam2; } );

    auto f1 = [](auto p) { return (p.bParam ? p.dParam1 : p.c1.mVal) < p.mVal; };
    auto f2 = [](auto p) { return ((p.dParam1 & p.dParam2) == 0) == p.bParam; };

    auto f = val < 3 ? f1: f2;
    DoWork(f);
}

中,您需要将auto p更改为DoWorkParams p,但是lambdas的auto功能是编译器支持的首批功能之一,所以它可能有效。

如果多个不同的函数共享参数,则可以使用继承。

struct DoWorkBaseParams {
  uint32_t dParam1;
  uint32_t dParam2;
  bool bParam;
  float fParam1;
  float fParam2;
};
struct DoWorkParams1:DoWorkBaseParams {
  MyClass& c1;
  MyClass2& c2;
};
struct DoWorkParams2:DoWorkBaseParams {
  MyClass& c1;
  MyClass3& c3;
};