给出opaque类型的声明(cheader.h)
typedef struct internal_data * Opaque;
我想宣布" internal_data"作为模板的一个实例(cppheader.h)
namespace Lib {
template<typename T>
struct Internal {
T data;
};
template<typename T>
Internal<T>* Initialise(T data) {
Internal<T>* t = new Internal<T>();
t->data = data;
return t;
}
}
以下函数编译:
#include "cppheader.h"
#include "cheader.h"
int main(int argc, char** argv)
{
Opaque o = Lib::Initialise(argc);
return 0;
}
我无法修改C标头。 C ++标题没有公开,所以我可以随意修改它。实例化的模板需要是POD。 为简单起见,我在C头上有多个不透明类型。它们都应该取消引用C ++模板的实例化。
我已经尝试了
typedef Lib::Internal<int> internal_data;
和
struct internal_data : Lib::Internal<int> {};
但是没有编译。
答案 0 :(得分:1)
从我可以看出,这看起来是C到C ++的典型特征,反之亦然API映射。
鉴于您无法更改C头文件,Opaque
的定义受到限制,并且基本上无法键入C ++头文件中包含的任何C ++构造。
纯粹意义上有点丑陋,但你可以使用reinterpret_cast
。
在cppheader中;
struct internal_data {};
template<typename T>
struct Internal {
T data;
};
template <typename T>
Opaque map_internal(Internal<T>* p)
{
return reinterpret_cast<Opaque>(p);
}
template <typename T>
Internal<T>* remap_internal(Opaque p)
{
return reinterpret_cast<Internal<T>*>(p);
}
然后内部Initialise
更改为;
template<typename T>
Opaque Initialise(T data) {
Internal<T>* t = new Internal<T>();
t->data = data;
return map_internal(t);
}
您没有提及有关资源管理的任何内容,但map_internal
的反面可用于在需要时将Opaque
强制转换回相应Internal<T>
的{{1}}
注意:类型安全是一个问题(w.r.t。delete
),但在这种情况下,权衡是类型安全与互操作性。由于严格别名,您应该不尝试访问可能(将来)在reinterpret_cast
中的任何数据,它只是从internal_data
转换回来。
值得注意的是cppreference,转换5,与C ++规范5.2.10相关。
任何指向T1类型对象的指针都可以转换为指向另一种类型cv T2的对象的指针。这完全等同于
Internal<T>
。
答案 1 :(得分:1)
如果您不想reinterpret_cast<>
,则可以继承虚拟internal_data
,即
struct internal_data {};
template<typename T>
struct Internal: internal_data {
T data;
};
当您需要访问刚从指向模板类型的指针转发的数据时。
答案 2 :(得分:0)
也许工会有帮助?
template<typename T>
union InternalExtend
{
Internal<T>* internal;
Opaque opaque;
};
template<typename T>
Opaque Initialise(T data) {
InternalExtend<T> ret;
ret.internal = new Internal<T>();
ret.internal->data = data;
return ret.opaque;
}