c++ - How to emulate a variable template as a class member? -


i'd have opinion on how emulate variable template class member. having data member in class dependent on template, not on class template. conceptually, written :

class m { private:     template<typename t>     somethingthatcoulddependont<t> m_datamember; }; 

my first thought make :

#include <iostream>  class { public :     template<typename t>     void mymethod()      {          static int = 0;         std::cout << "my method : " << << " calls" << std::endl;         a++;     } };   int main() {     a, b;     a.mymethod<int>();     a.mymethod<int>();     a.mymethod<double>();     b.mymethod<double>();     return 0; } 

but doesn't work because static member in mymethod isn't per instance per method generated. actually, makes sense mymethod can seen global function taking first parameter object of type (without taking account visibility concerns). came other idea :

#include <iostream> #include <vector>  class { public :     a() : i(-1) {}     template<typename t>     void mymethod()      {          static std::vector<int> a;         static int max = 0;         if(i < 0)         {             = max;             a.push_back(0);             max++;         }         std::cout << "my method : " << a[i] << " calls" << std::endl;         a[i]++;     } private:     int i; };   int main() {     a, b;     a.mymethod<int>();     a.mymethod<int>();     a.mymethod<double>();     b.mymethod<double>();     return 0; } 

but don't it, if improved reusing integers unused or using more appropriate container.

i want think might have better solution problem here, that's why i'm asking.

you can creating map type_info pointer type-specific data.

here's example:

#include <iostream> #include <map> #include <typeinfo>  // custom comparison operator uses std::type_info::before member // function.  comparing pointers doesn't work since there no // guarantee typeid operator gives same object // same type. struct beforetype {   bool operator()(const std::type_info *a,const std::type_info *b) const   {     return a->before(*b);   } };  struct {   template <typename t>   int &member()   {     return member_map[&typeid(t)];   }    std::map<const std::type_info *,int,beforetype> member_map; };  int main(int,char**) {   a1, a2;   ++a1.member<int>();   ++a1.member<int>();   ++a1.member<double>();   ++a2.member<int>();   std::cout << a1.member<int>() << "\n";   std::cout << a1.member<double>() << "\n";   std::cout << a1.member<float>() << "\n";   std::cout << a2.member<int>() << "\n";   return 0; } 

the output is:

2 1 0 1 

if interested in container of values of different types, use this:

#include <iostream> #include <map> #include <typeinfo>   struct beforetype {   bool operator()(const std::type_info *a,const std::type_info *b) const   {     return a->before(*b);   } };  struct value {   virtual ~value() { }   virtual value *clone() = 0; };  template <typename t> struct basicvalue : value {   t value;   basicvalue() : value() { }   basicvalue(const t &value) : value(value) { }   virtual value *clone() { return new basicvalue(value); } };  struct typemap {   typemap() { }    typemap(const typemap &that)   {     add(that.value_map);   }    template <typename t>   t &value()   {     valuemap::iterator iter = value_map.find(&typeid(t));     if (iter==value_map.end()) {       basicvalue<t> *member_ptr = new basicvalue<t>;       value_map.insert(valuemap::value_type(&typeid(t),member_ptr));       return member_ptr->value;     }     return static_cast<basicvalue<t> *>(iter->second)->value;   }    typemap &operator=(const typemap &that)   {     clear();     add(that.value_map);     return *this;   }    void clear()   {     while (!value_map.empty()) {       value *member_ptr = value_map.begin()->second;       value_map.erase(value_map.begin());       delete member_ptr;     }   }    ~typemap()   {     clear();   }    private:         typedef std::map<const std::type_info *,value *,beforetype> valuemap;     valuemap value_map;      void add(const valuemap &value_map)     {       valuemap::const_iterator iter = value_map.begin(), end = value_map.end();       (;iter!=end;++iter) {         this->value_map[iter->first] = iter->second->clone();       }     } };  int main(int,char**) {   typemap type_map;   type_map.value<int>() = 5;   type_map.value<float>() = 2.5;   type_map.value<std::string>() = "hi";   std::cout << type_map.value<int>() << "\n";   std::cout << type_map.value<float>() << "\n";   std::cout << type_map.value<std::string>() << "\n";   return 0; } 

the output is:

5                                                                                       2.5                                                                                     hi   

however, if using boost, can simplified significantly:

struct typemap {   template <typename t>   t &value()   {     boost::any &any_value = value_map[&typeid(t)];     if (any_value.empty()) {       any_value = t();     }     return *boost::any_cast<t>(&any_value);   }    private:     std::map<const std::type_info *,boost::any,beforetype> value_map; }; 

with c++11, can rid of custom comparison using std::type_index:

struct typemap {   template <typename t>   t &value()   {     boost::any &any_value = value_map[std::type_index(typeid(t))];     if (any_value.empty()) {       any_value = t();     }     return *boost::any_cast<t>(&any_value);   }    private:     std::map<const std::type_index,boost::any> value_map; }; 

Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -