Alexis
Alexis

Reputation: 2179

How can I have a container of template elements

I am trying to have a container of template elements but it's not compiling because the first argument is not given

So I want to put the following class in a std::map

  template <typename T>
  class TemplateParam
  {
    ITemplateParam<T>   param_;
  public:
    TemplateParam(T value)
    {
      if (sizeof(value) >= sizeof(void*))
        param_ = ptrTemplateParam<T>(value);
      else
        param_ = cpyTemplateParam<T>(value);
    }
    const T &getParam() const { return param_.getParam(); }
  };

ITemplateParam

  template <typename U>
  class ITemplateParam
  {
  public:
    virtual ~ITemplateParam(){}
    virtual const U&    getParam() const = 0;
  };

I think I understand why I can't put elements of different sizes in a container, it's why I used ptrTemplateParam and cpyTemplateParam. (I have also tried with the shared_ptr)

Do you have any idea how can I resolve my problem

I can use boost library

I have looked at this link but I don't know how can I declare the getter.

Edit:

Thanks to your answer I am able to store it in a map but I'm not able to insert an element in the map and I have to use void*

So I have changed my class to:

  class ITemplateParam
  {
  public:
    virtual ~ITemplateParam(){}
    virtual const void *getParam() const = 0;
  };

  template <typename U>
  class ptrTemplateParam : public ITemplateParam
  {
    U   param_;
  public:
    ptrTemplateParam(U & param) : param_(param) {}
    virtual const void  *getParam() const { return param_; }
  };

  class TemplateParam
  {
    std::shared_ptr<ITemplateParam>     param_;
  public:
    template <typename T>
    TemplateParam(T value): param_(ptrTemplateParam<T>(value))
    {
    }

    const void *getParam() const { return param_->getParam();}
  };

and I try to do

std::map<std::string, TemplateParam>  m_;
m_["integer"] = TemplateParam(5);

Edit2 boost::any was the solution

Upvotes: 1

Views: 187

Answers (2)

&#214;&#246; Tiib
&#214;&#246; Tiib

Reputation: 10979

If you need to have a container that contains elements of different type then you have basically 3 ways:

  1. Have container of variants or unions.
  2. Have container of polymorphic pointers or polymorphic smart pointers.
  3. Use intrusive container.

It is unclear from your question what would be best for you.

Upvotes: 3

lip
lip

Reputation: 688

IMHO, if you want to put different items in the same container, you should consider using Boost.Variant. This is not a direct answer to your actual example here, but I found this pattern very useful for this category of problems. You avoid using pointers and enforcing inheritance in an elegant way.

class A {};
class B {};

typedef boost::variant<A, B> item_t;
...
vector<item_t> my_container;

Upvotes: 2

Related Questions