带有move构造函数的c++接口适配器类
adapter class for C++ interface with move constructor
我正试图为接口类编写一个adapter
类,该接口类接受a)接口的实现,应该是堆栈分配的(因此不应该从外部需要新的/删除处理,适配器本身可以使用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 lambdan"; 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();
^
- 我完全不明白这个错误,我希望你能解释一下
- 我如何才能真正正确地实现
adapter(interface&&)
构造器?我可能需要在堆上创建对象的副本,否则在adapater
构造函数 之后它将无法持久。
在ideone: http://ideone.com/Gz3ICk与c++ 14 (gcc-5.1)测试
PS:是的,adapter
类缺少一个析构函数,它应该删除从lambda构造函数创建的obj
Try with
adapter b {implementation()};
问题是
adapter b(implementation());
没有被解释为(如果我没记错的话)adapter
类型对象的实例化,而是被解释为名称为b
的函数声明,接收一个类型为接受一个(未命名的)参数,该参数也是一个函数,返回类型实现,不接受参数[由songyuananyao更正],返回一个implementation
的对象,adapter
。
我知道两种方法来解决这个歧义
1)添加一对括号
adapter b((implementation()));
2)使用基于大括号
的新的统一初始化样式adapter b {implementation()};
我建议使用形式2,因为你使用c++ 11并且(恕我直言)它更清晰。
——添加解决生命周期问题的示例——
要解决impl
的复制/克隆/生存期,那么…您正在使用指向纯虚基类的指针;我认为唯一的解决方案是克隆派生类。
我提出了一个解决方案
1)将adapter
中的obj
从interface *
切换到std::unique_ptr<interface>
(以避免释放问题)
2)在interfece
中添加一个返回std::unique_ptr<interface>
的纯虚拟成员clone()
3)添加了一个中间模板类(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 lambdan"; return 99; });
a.obj->hello();
adapter b { implementation() };
b.obj->hello();
return 0;
}
注。:对不起,我的英语不好
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 创建包装升压适配器的自定义范围类
- 在 C++20 中将多个范围适配器连接到一个范围中
- 递归应用 C++20 范围适配器会导致编译时无限循环
- Lambda 到函数指针适配器的理解
- 返回迭代器以提升适配器转换的容器
- 将 Kleene 运算符解析为一组替代方案,适配器? 与精神 x3
- Boost Range适配器制作集合
- 升压范围适配器
- DXGI 集成适配器
- 克隆设计模式适配器 - 避免切片子项(类似于原型模式)
- 为什么不支持容器适配器中元素的初始化和迭代
- C++ 提升范围:any_range和转换适配器
- 用于隐藏结构细节的迭代器适配器
- 如何在 DirectX 11 应用程序中提供选择图形适配器的选项?
- 适配器模式:支持可以是const或非const的基础数据,优雅
- 如何对VC 17/20的分配适配器现代化
- 在C++中使用 WMI 获取适配器的接口索引
- 带有move构造函数的c++接口适配器类