c++ - Passing pointers to different variable types to a function and reuse them later for assignmet -
in gui based project need page1 mark variable to changed , call page2, page2 reads user's input , updates marked variable new value. variable type different , variables held external linked library.
how achieve without creating fname_uint8, fname_uint16, fname_giventype variants markers , setters?
this example sums scenario:
there varholder
class holds lot of structs lot of variables, e.g.:
class varholder { public: typedef struct { int8_t var1; int16_t var2; int32_t var3; char str1[40]; float var4; } struct1_t; /* ...continues... */ struct1_t struct1; }
now class firststage
wants mark 1 variable change, , calls member of committer_instance
instance of class committer
class firststage { /* ... */ void dofirststage(void) { /* globally defined committer instance */ g_committer_instance->mark_var_change(&varholder_instance->struct1.var1); } }
committer::mark_var_change(t*)
defined follows:
template <typename t> void committer::mark_var_change(t *var) { /* store pointer variable */ /* save somewhere preserving type */ = var; }
a member of secondstage
, finally, wants use available value update variable marked change through same g_committer_instance
, this:
class secondstage { /* ... */ template <typename t> void dosecondstage(t new_value) { g_committer_instance->commit_change(new_value); } }
where committer::commit_change(t)
defined follows:
template <typename t> void committer::commit_change(t new_value) { /* dereferencing stored pointer */ *(/*whatever stored before*/) = new_value; }
of course not able realize type-indipendent "marker , retriever" can seamlessy update variable based upon address. suggestion appreciated.
mcve
### varholder.h #include <stdint.h> class varholder { public: varholder() {} virtual ~varholder() {} typedef struct { int8_t var1; uint8_t var2; int64_t var3; char str1[40]; } struct1_t; struct1_t struct1; } ### firststage.h #include global.h class firststage { public: firststage() {} ~firststage() {} void dofirststage(void) { /* globally defined committer instance */ g_committer_instance->mark_var_change(&varholder_instance->struct1.var1); } } ### secondstage.h #include global.h class secondstage { public: secondstage() {} ~secondstage() {} template <typename t> void dosecondstage(t new_value) { g_committer_instance->commit_change(new_value); } } ### committer.h #include global.h class committer { public: committer() {} ~committer() {} template <typename t> void committer::mark_var_change(t *var) { /* store pointer variable */ /* save somewhere preserving type */ = var; } template <typename t> void committer::commit_change(t new_value) { /* dereferencing stored pointer */ *(/*whatever stored before*/) = new_value; } } ### global.h #include varholder.h #include committer.h extern committer *g_committer_instance; extern varholder *varholder_instance; ### main.cpp #include global.h #include varholder.h #include firststage.h #include secondstage.h committer *g_committer_instance; varholder *varholder_instance; int main() { g_committer_instance = new committer(); varholder_instance = new varholder(); firststage *fstage = new firststage(); secondstage *sstage = new secondstage(); int8_t var_new = 100; /* first stage */ fstage->dofirststage(); /* second stage */ sstage->dosecondstage(var_new); return 0; }
you may use void*
without (unsafe) or typeid
:
class committer { public: template <typename t> void mark_var_change(t *var) { mpointer = var; mtypeinfo = &typeid(t*); } template <typename t> void commit_change(t new_value) { if (*mtypeinfo != typeid(t*)) { throw std::runtime_error("bad type"); } if (mpointer == nullptr) { throw std::runtime_error("nullptr stocked"); } *reinterpret_cast<t*>(mpointer) = new_value; } private: void* mpointer = nullptr; const std::type_info* mtypeinfo = nullptr; };
- without typeid live example
- with typeid live example
or safer boost::any
manage type:
class committer { public: template <typename t> void mark_var_change(t *var) { mpointer = var; } template <typename t> void commit_change(t new_value) { t* pointer = boost::any_cast<t*>(mpointer); // throw bad type if (pointer == nullptr) { throw std::runtime_error("nullptr stocked"); } *pointer = new_value; } private: boost::any mpointer; };
Comments
Post a Comment