带有移动构造函数的 C++ 接口的适配器 class

adapter class for C++ interface with move constructor

我正在尝试为接口 class 编写 adapter class 接受 a) 接口的实现,它应该是堆栈分配的(所以没有 new/delete 应该需要从外部进行处理,适配器本身可以使用 new/delete) 和 b) 将由接口的相应实现调用的 lambda 函数。

#include <iostream>
#include <functional>

struct interface {
  virtual int hello() = 0;
};

struct implementation : public interface {
  virtual int hello() {
    std::cout << "hello()\n";
    return 42;
  }
};

struct adapter {
  interface* obj;

  adapter(std::function<int()>&& func) {
    struct lambda : public interface {
      std::function<int()> func;
      lambda(std::function<int()> func_): func(func_) { }
      virtual int hello() {
        return this->func();
      }
    };
    this->obj = new lambda{func};
  }

  adapter(interface&& impl) {
    // TODO: pretty sure that's incorrect
    //       but can I somehow create a copy of "impl" on the heap?
    this->obj = &impl;
  }
};

int main() {
  adapter a([]() { std::cout << "hello from lambda\n"; return 99; });
  a.obj->hello();

#if 0
  // ERROR
  adapter b(implementation());
  b.obj->hello();
#endif
  return 0;
}

这是启用 adapter b 部分时出现的错误。

prog.cpp: In function 'int main()':
prog.cpp:39:4: error: request for member 'obj' in 'b', which is of non-class type 'adapter(implementation (*)())'
  b.obj->hello();
    ^
  1. 我完全不明白这个错误,非常感谢您的解释
  2. 我怎样才能真正正确地实现 adapter(interface&&) 构造函数?我可能需要在堆上创建对象的副本,否则在 adapater 构造函数
  3. 之后它不会持久化

在 ideone 上测试:http://ideone.com/Gz3ICk 使用 C++14 (gcc-5.1)

PS:是的,adapter class 缺少应删除从 lambda 构造函数

创建的 obj 的析构函数

试试

adapter b {implementation()};

问题在于

adapter b(implementation());

没有被解释(如果我没记错的话)类型为 adapter 的对象的实例化,而是被解释为名称为 b 的函数的声明 receive an object of type implementation takes a single (unnamed) parameter which is also a function, returning type implementation and take no parameters [Songyuanyao 更正] 和 return一个adapter.

我知道解决这个歧义的两种方法

1) 添加一对括号

adapter b((implementation()));

2) 使用基于大括号的新统一初始化样式

adapter b {implementation()};

我建议使用表格 2,因为您使用的是 C++11,并且(恕我直言)它更清晰。

---添加了解决生命周期问题的例子---

要解决impl的copy/clone/lifetime,嗯……你用的是指向纯虚基的指针class;我看到的唯一解决方案是克隆派生的 class.

我提出一个解决方案

1) 将 adapter 中的 objinterface * 切换为 std::unique_ptr<interface>(以避免释放问题)

2) 在 interfece 中添加了一个纯虚拟成员 clone() 即 return 一个 std::unique_ptr<interface>

3) 添加了一个中间模板 class (interHelper) 以实现 clone() 一次

以下是我提出的解决方案

#include <memory>
#include <iostream>
#include <functional>

struct interface
 {
   virtual int hello() = 0;
   virtual std::unique_ptr<interface> clone () const = 0;
 };

template <typename D>
struct interHelper : public interface 
 {
   std::unique_ptr<interface> clone() const override
    { return std::unique_ptr<interface>(new D((const D &)(*this))); }
 };

struct implementation : public interHelper<implementation>
 {
   int hello() override
    {
      std::cout << "hello()\n";
      return 42;
    }
 };

struct adapter
 {
   struct lambda : public interHelper<lambda>
    {
      std::function<int()> func;

      lambda (std::function<int()> func_): func(func_)
       { }

      int hello() override
       { return this->func(); }
    };

   std::unique_ptr<interface>  obj;

   adapter (std::function<int()>&& func) : obj { lambda{func}.clone() }
    { }

   adapter (interface&& impl) : obj { impl.clone() }
    { }
 };

int main()
 {
   adapter a([]() { std::cout << "hello from lambda\n"; return 99; });

   a.obj->hello();

   adapter b { implementation() };

   b.obj->hello();

   return 0;
 }

p.s.: 对不起我的英语不好