c++ - How to dynamically determine the types used to parameterise a template and compare them -


if 1 creates class template based on 1 or more type parameters, how 1 query these types @ runtime?

for example:

template <typename t> class foo {  public:   typedef t typet;    foo() {}    // assume in range   void set(size_t i, t value) { store[i] = value; }   t get(size_t i) { return store[i]; }    void fast_copy(t* dest) { memcpy(dest, store, 100 * size_of(t)); }    // ugly public data member   t store[100]; };   void main() {   foo<double> fd;   foo<int> fi;    // not c++!   if (fd::typet == fi::typet) {      // fast copy since types match     fd.fast_copy(fi.store);    } else {      // slower item copy since types don't match     // , let runtime perform type conversion:     (size_t = 0; < 100; ++i) {       fi.set(i, static_cast<fd::typet>(fd.get(i)));     }   } } 

the reason want because have runtime objects contain either arrays of floats, doubles or ints, , want copy them array of different type, don't know types determined @ runtime. in above example, types used instantiate fi , fd known, in full example fi , fd references polymorphic class containers of array of basic numerical type.

this mechanism intended runtime configurable bridge between set of functions return arrays of floats, doubles or ints, , set requires arrays of floats, doubles, or ints, , types may or may not same on both sides of bridge. bridge non-trivial , few other things, needs take array (or container of array) of 1 type in, , produce array (or container of array) of type @ other end, in cases types same , not.

note: related this previous question of mine , replace if 1 makes more sense.

edit: here's bit more info on i'm trying do.

i have system on 1 side consists of set of functions return numerical results. return single float or double, single int, modify (hence 'return') array of floats, or doubles, or ints. there's whole bunch of them. want associate each 1 (well, actually, returned data, functions don't matter) call "source" object - might source<t>, t numerical type. although might need sourcescalar<t> , sourcevector<t> handle single values or arrays. anyway, object entry point "bridge". each source<t> object stored in heterogenous collection of source objects, , referenced unique "source key". example, 1 such source-associated function might return array of 32 floats representing latest output wavetable oscillator. might return array of 32 doubles representing peak detector output on 32 samples.

on other side of system have yet set of functions. these take numerical values parameters. require single float or double, single int, require arrays of same. there's whole bunch of these too. have call "dest" object - dest<t>, or maybe destscalar<t>, destvector<t> above. object stores std::function wrapper tied 1 of these functions, can invoke function when necessary. each dest object stored in hetereogenous collection of dest objects, , referenced unique "dest key". example, 1 such function might digital filter expects receive arrays of size 32, of doubles not floats.

now, @ runtime, higher-level system (actually controlled user) required arbitrarily associate source dest. user provides 2 keys - source , dest - , system 'connects' data on 1 side function on other. in example above, might try connect 32-float array wavetable oscillator 32-double array parameter of digital filter. @ time association might removed, too. if 32-double array peak detector connected 32-double array parameter of digital filter, want transfer/copy fast possible because arrays of same type.

edit 2: here code compiles , simplest case can construct creates 2 collections of source , dest objects, , dynamically attempts 'connect' them. first 2 calls source_collection[1]->set(...) work correctly, second 2 not, , end calling basedest base class member function set_item rather 1 in dest<t>. uses observation typeid() returns static pointer if type queried same, , compares values of these pointers determine type matches. unsafe, might best use enums instead.

this feels horrible me - there must better way?

#include <vector> #include <typeinfo> #include <cassert> #include <boost/shared_ptr.hpp> #include <boost/function.hpp>  class source;    // fwd class basedest;  // fwd  typedef boost::shared_ptr<source>   sourceptr; typedef boost::shared_ptr<basedest> basedestptr;  // target function takes array of doubles void target_func_vd(double *array, size_t len) {   (size_t = 0; < len; ++i) {     assert(array[i] == i);   } }  // target function takes array of floats void target_func_vf(float *array, size_t len) {   (size_t = 0; < len; ++i) {     assert(array[i] == i);   } }  // base class dest class basedest { public:   basedest() {}   virtual ~basedest() {}    virtual void set(float *array, size_t len)  { /* not implemented, can't pure */ };   virtual void set(double *array, size_t len) { /* not implemented, can't pure */ };    virtual void set_item(size_t index, double item) { /* not implemented, can't pure */ };   virtual void set_item(size_t index, float item) { /* not implemented, can't pure */ };   virtual void finished(size_t len) = 0;    virtual const std::type_info* get_type_info() const = 0; private: };  template <typename t> class destvector : public basedest { public:   typedef boost::function<void (t *, size_t)> callable;    explicit destvector(callable callable) : callable_(callable) { }    virtual void set(t *array, size_t len) { callable_(array, len); }   virtual void set_item(size_t index, t item) { buffer_[index] = item; }   virtual void finished(size_t len) { callable_(buffer_, len); }    virtual const std::type_info* get_type_info() const { return &typeid(t); }; private:   callable callable_;   t buffer_[256]; };  // 'set' overloaded array type class source { public:   source() {}   void connect(const basedestptr& dest) { dest_ = dest; }    void set(float *array, size_t len) {     if (dest_->get_type_info() == &typeid(double)) {       // convert double       (size_t = 0; < len; ++i) {         dest_->set_item(i, array[i]);  // calls base member function       }       dest_->finished(len);     } else if (dest_->get_type_info() == &typeid(float)) {       dest_->set(array, len);     }   }    void set(double *array, size_t len) {     if (dest_->get_type_info() == &typeid(float)) {       // convert float       (size_t = 0; < len; ++i) {         dest_->set_item(i, array[i]);  // calls base member function       }       dest_->finished(len);     } else if (dest_->get_type_info() == &typeid(double)) {       dest_->set(array, len);     }   }  private:   basedestptr dest_; };   void main() {    // test arrays   float float_array[256];   (size_t = 0; < 256; ++i) {     float_array[i] = static_cast<float>(i);   }    double double_array[256];   (size_t = 0; < 256; ++i) {     double_array[i] = static_cast<double>(i);   }    // collection of sources   std::vector<sourceptr> source_collection;    sourceptr s0(new source());   source_collection.push_back(s0);    sourceptr s1(new source());   source_collection.push_back(s1);     // collection of dests   std::vector<basedestptr> dest_collection;    basedestptr t0(new destvector<float>(&target_func_vf));   dest_collection.push_back(t0);    basedestptr t1(new destvector<double>(&target_func_vd));   dest_collection.push_back(t1);     // create , invoke connections   source_collection[0]->connect(dest_collection[0]);   source_collection[0]->set(float_array, 256);  // should end passing float_array target_func_vf, ,    source_collection[0]->connect(dest_collection[1]);   source_collection[0]->set(double_array, 256); // should end passing double_array target_func_vd, ,    source_collection[1]->connect(dest_collection[0]);   source_collection[1]->set(double_array, 256); // should end passing double_array target_func_vf, doesn't    source_collection[1]->connect(dest_collection[1]);   source_collection[1]->set(float_array, 256); // should end passing float_array target_func_vd, doesn't } 

you can use overloads. add class

void copy(t & dest) {    fast_copy(&dest): }  template<class u> void copy(u & dest) {    (size_t = 0; < 100; ++i) {       dest.set(i, static_cast<typet>(get(i))); } 

ps: more c++ way define copy-constructor or assignment operator

edit: if want dynamic mke things more polymorphic

struct basedest {    virtual void assign(const double * v, size_t cnt) = 0;    virtual void assign(const float * v, size_t cnt) = 0; //etc }  template<class t> struct destimpl {    void assign(const double * v, size_t cnt)    {        assign_impl(v, cnt);    }    void assign(const float * v, size_t cnt)    {        assign_impl(v, cnt);    }     template<class u>    void assign_impl(const u * v, size_t cnt)    {       (size_t = 0; < cnt; ++i) {          set(i, static_cast<t>(v[i])));    }     template<>    void assign_impl<t>(const t * v, size_t cnt)    {       fast_copy(v, cnt);    } //stuff }  struct source { //blah    template<class t>    void set(const t * v, size_t cnt)    {      dest_->set(v, cnt);    }  //blah } 

Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -