簡體   English   中英

如何使用模板化的C ++結構定義C-forward聲明的不透明結構

[英]How to define C-forward declared opaque struct with a templated C++ struct

給定不透明類型的C聲明(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> {};

但都沒有編譯。

據我所知,這看起來是C到C ++的典型代表,反之亦然。

鑒於您無法更改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>進行相應的delete

注意:這里需要考慮類型安全性(將reinterpret_cast ),但是在這種情況下,需要權衡的是類型安全性與互操作性。 由於嚴格別名,你應該試圖訪問可能(在未來)是任何數據internal_data ,它的存在只是為了從轉換和回Internal<T>

此處值得注意的是cppreference ,轉換5,與C ++規范5.2.10相關。

指向類型T1的對象的任何指針都可以轉換為指向另一類型cv T2的對象的指針。 這完全等同於

static_cast<cv T2*>(static_cast<cv void*>(expression))

現場樣品

如果您不想reinterpret_cast<> ,則可以從虛擬internal_data繼承,即

struct internal_data {};
template<typename T>
struct Internal: internal_data {
    T data;
};

當您需要訪問數據時,只需將指針向下轉換到模板類型即可。

工會會有所幫助嗎?

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM