class C {
public
T x;
};
x のコンストラクターが、構築しているC のインスタンスを 暗黙のうちに知るエレガントな方法はありますか?
私は、いくつかの汚れた洗練されていない機械でそのような動作を実装しました。これは、sqlite3 ラッパーに必要です。私が見たすべてのラッパーが好きというわけではありません.API IMOは醜く不便です. 私はこのようなものが欲しい:
class TestRecordset: public Recordset {
public:
// The order of fields declarations specifies column index of the field.
// There is TestRecordset* pointer inside Field class,
// but it goes here indirectly so I don't have to
// re-type all the fields in the constructor initializer list.
Field<__int64> field1;
Field<wstring> field2;
Field<double> field3;
// have TestRecordset* pointer too so only name of parameter is specified
// in TestRecordset constructor
Param<wstring> param;
virtual string get_sql() {
return "SELECT 1, '1', NULL FROM test_table WHERE param=:PARAM";
}
// try & unlock are there because of my dirty tricks.
// I want to get rid of them.
TestRecordset(wstring param_value)
try : Recordset(open_database(L"test.db")), param("PARAM") {
param = param_value;
// I LOVE RAII but i cant use it here.
// Lock is set in Recordset constructor,
// not in TestRecordset constructor.
unlock(this);
fetch();
} catch(...) {
unlock(this);
throw;
}
};
I want to clarify the fact - it is a part of the working code. You can do this in C++. I just want to do it in a more nice way.
I've found a way to get rid of unlock and try block. I've remembered there is such a thing as thread local storage. Now I can write constructor as simple as that:
TestRecordset(wstring param_value):
Recordset(open_database(L"test.db")), param("PARAM") {
param = param_value;
fetch();
}
to dribeas:
My objective is to avoid redundant and tedious typing. Without some tricks behind the scene I will have to type for each Field and Param:
TestRecordset(wstring param_value): Recordset(open_database(L"test.db")), param(this, "PARAM"),
field1(this, 0), field2(this, 1), field3(this, 2) { ... }
それは冗長で、醜く、不便です。たとえば、SELECT の途中で新しいフィールドを追加する必要がある場合は、すべての列番号を書き直す必要があります。あなたの投稿に関するいくつかのメモ:
- フィールドと Paramsは、デフォルトのコンストラクターによって初期化されます。
- コンストラクター内の初期化子の順序は関係ありません。フィールドは常に宣言順に初期化されます。この事実を使用して、フィールドの列インデックスを追跡しました
- 基本クラスが最初に構築されます。したがって、Fields が作成されると、Recordset の内部フィールド リストは、Filed の既定のコンストラクターで使用できるようになります。
- ここではRAIIを使用できません。Recorset コンストラクターでロックを取得し、すべての Fields が構築された後に TestRecordset コンストラクターで強制的に解放する必要があります。