【问题标题】:User higher order functions in C++ 14C++ 14 中的用户高阶函数
【发布时间】:2021-10-11 11:04:23
【问题描述】:

我想创建一个类来接受由 Arduino 中的另一个函数创建的函数。我在搜索和大量试验和错误后得到的“最接近”(没有std::function,因为我们在 Arduino 和 C++ 14 中):

foo.h

class Foo {
  private:
    template<typename Functor>
    Functor _lambda;

  public:
    template<typename Functor>
    Foo(Functor lambda);

    static auto create_lambda(int a) {
      return [a](int b) mutable { ... }
    }
};

foo.cpp

template<typename Functor>
Foo::Foo (Functor lambda) : _lambda(lambda) {}

bar.cpp

new Foo(Foo::create_lambda(2));

上面的代码产生了一些错误,包括:

error: data member '_lambda' cannot be a member template
error: 'Foo::Foo(Functor) [with Functor = Foo::create_lambda(int)::<lambda(bool)>]', declared using local type 'Foo::create_lambda(int)::<lambda(bool)>', is used but never defined

另外,如果有帮助的话,很高兴使用 C++ 17。

【问题讨论】:

  • 你的代码有什么问题?
  • 类成员不能是模板,只有类方法可以。抱歉,C++ 不能以这种方式工作。你的整个班级必须是一个模板。此外,还必须更改许多其他基本的东西才能使其工作(例如,将模板定义放在.cpp 文件中总是以泪水结束)。 C++17 也是如此,未来的所有其他 C++ 版本也可能如此。只需使用std::function,就更简单了。
  • @SamVarshavchik,听起来都不错,只是他们运行的 Arduino 环境可能没有std::function,因此他们要求不使用。常见的基于 AVR 的 Arduino 环境提供了接近 C99 托管的 C 标准库的东西,但根本没有 C++ 标准库;没有std::swapstd::array,更不用说std::function
  • 所以你要求为arduino实现std::function
  • 如果只将无星 lambda 传递给构造函数,则只需使用指向函数的指针。

标签: c++ arduino higher-order-functions


【解决方案1】:

类必须被模板化,而不是成员:

// Put this whole thing in the header file. 
// It has to go there b/c templates have to be in the header.
template<class F>
class Foo {
    F func;
   public:
    Foo() = default;
    Foo(Foo const&) = default;
    Foo(Foo&&) = default;
    Foo(F f) : func(f) {}

    // Example invoke member function
    int invoke(int value) {
        return func(value);
    }
};

在C++17中,我们可以通过为Foo添加模板推导指南,在制作Foo时自动判断F的类型:

// Put this after the class declaration
template <class F>
Foo(F) -> Foo<F>;

那么,我们就可以很轻松地使用它了!

// Template parameter is implicit
Foo myFoo = [](int x) { return x * x; };
// myFoo now has type Foo<(anonymous lambda)>

如果你绝对需要运行时多态,你可以有一个接口,每个Foo&lt;F&gt;都扩展:

class Invokable {
    virtual int invoke(int) = 0;
    virtual ~Invokable() = default;  
};

template <class F>
class Foo : Invokable {
    // ...
};

这篇关于std::function 实现方式的文章提供了比我在堆栈溢出帖子中更多的细节:https://shaharmike.com/cpp/naive-std-function/

附录: You can see a working example here.

使用优化编译时,程序集非常紧凑。 C++ 的好处之一是使用 lambda 或模板没有开销,而且它们对编译器完全透明。

(虚拟函数是不透明的,这就是为什么我尽量避免它们,但有时你确实需要运行时多态)

.LC0:
        .string "The square of %i is %i\n"
main:
        push    rbx
        xor     ebx, ebx
.L2:
        mov     edx, ebx
        mov     esi, ebx
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        imul    edx, ebx
        add     ebx, 1
        call    printf
        cmp     ebx, 11
        jne     .L2
        xor     eax, eax
        pop     rbx
        ret

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    相关资源
    最近更新 更多