次の大まかな例のように、特定のセッターとゲッターを介してアクセスする必要がある不透明なフィールドを持つ一部の構造を持つ既存のCライブラリ(変更できません)を使用しています(x
Cで記述されている場合でも、想像はプライベートです) 。
struct CObject {
int x;
};
void setCObjectX(CObject* o, int x) {
o->x = x;
}
int getCObjectX(CObject* o) {
return o->x;
}
私は、より複雑ではありますが、ラッパーのようなこれらのタイプの構造を個人的に所有するクラスを作成しています。関連するフィールドを便利な方法で公開したいと思います。最初は、必要に応じてセッターとゲッターを書いていました。しかし、私は別のことを考えたので、この方法に欠点があるかどうかを知りたいと思いました。関数ポインタ(std::function
)を使用してCセッターとゲッターのペアを格納し、関数ではなくフィールドに直接アクセスするかのように表示します。
このような「偽の」フィールドを定義するために私が書いた汎用クラスは次のとおりです。
template<typename T>
struct IndirectField {
void operator=(const T& value) {
setter(value);
}
auto operator()() const -> T {
return *this;
}
operator T() const {
return getter();
}
std::function<void(const T&)> setter;
std::function<T()> getter;
};
これは、C ++クラスのインスタンスを定義し、設定することにより使用されsetter
且つgetter
対応するCの機能を有します。
IndirectField<int> x;
// ...
x.setter = [=](int x) {
setCObjectX(innerObject.get(), x);
};
x.getter = [=]() {
return getCObjectX(innerObject.get());
};
この方法を使用することに不利な点はありますか?それは最終的に危険な行動か何かにつながる可能性がありますか?
私はあなたのソリューションを参照して最大の問題は、ということであるstd::function
オブジェクトは、各インスタンス内のスペースを取るIndirectField
内部CPPObject
場合でも、CObject
タイプが同じです。
関数ポインタをテンプレートパラメータにすることで、この問題を修正できます。
template<typename T,typename R,void setter(R*,T),T getter(R*)>
struct IndirectField {
IndirectField(R *obj) : obj(obj) {
}
void operator=(const T& value) {
setter(obj, value);
}
auto operator()() const -> T {
return *this;
}
operator T() const {
return getter(obj);
}
private:
R *obj;
};
この実装の使用方法は次のとおりです。
class CPPObject {
std::unique_ptr<CObject,decltype(&freeCObject)> obj;
public:
CPPObject()
: obj(createCObject(), freeCObject)
, x(obj.get())
, y(obj.get()) {
}
IndirectField<int,CObject,setCObjectX,getCObjectX> x;
IndirectField<double,CObject,setCObjectY,getCObjectY> y;
};
このアプローチでは、2つのstd::function
オブジェクトを1つのCObject*
ポインタと交換しますIndirectField
。残念ながら、このポインタはテンプレート内のコンテキストから取得できないため、格納する必要があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加