C++ class with template member variable

前端 未结 2 1091
迷失自我
迷失自我 2020-11-30 20:33

I am trying to solve a programming problem that consists of an object (call it Diagram), that contains several parameters. Each parameter (the Parameter class) can be one of

相关标签:
2条回答
  • 2020-11-30 20:58

    The bellow implementation uses a few C++11 features but you will be able to pick them apart.

    #include <vector>
    #include <memory>
    
    class Parameter
    {
    private:
      class ParameterBase {
      public:
        virtual ~ParameterBase() {}
        virtual ParameterBase* copy() = 0;
        virtual void foo() = 0;
      };
    
      template <typename T>
      class ParameterModel : public ParameterBase {
      public:
        // take by value so we simply move twice, if movable
        ParameterModel(const T& t) : t(t) {}
        ParameterModel(T&& t) : t(t) {}
        void foo() { t.foo(); }
        ParameterModel* copy() { return new ParameterModel(*this); }
      private:
        T t;
      };
    
    public:
      template <typename T>
      Parameter(T&& t) 
        : pp(new ParameterModel< typename std::remove_reference<T>::type >(std::forward<T>(t))) {}
    
      // Movable and Copyable only
      Parameter(Parameter&&) = default;
      Parameter& operator=(Parameter&&) = default;
    
      Parameter(const Parameter& other) : pp(other.pp->copy()) {};
      Parameter operator=(const Parameter& other) {
        pp.reset(other.pp->copy());
        return *this;
      };
    
      // members
    
      void foo() { pp->foo(); }
    private:
      std::unique_ptr<ParameterBase> pp;
    };
    
    
    class Diagram
    {
    public:
      std::vector<Parameter> v;
      int type;
    };
    
    struct X {
      void foo() {}
    };
    
    struct Y {
      void foo() {}
    };
    
    int main()
    {
      Diagram d;
      d.v.emplace_back(X()); // int
    
      // parameters are copyable and can be reassigned even with different
      // impls
      Parameter p = d.v.back();
    
      Parameter other((Y()));
      other = p;
      return 0;
    }
    

    What does this code do? It hides the fact that we use inheritance to implement parameters from our users. All they should need to know is that we require a member function called foo. These requirements are expressed in our ParameterBase. You need to identify these requirements and add the to ParameterBase. This is basically a more restrictive boost::any.

    It is also quite close to what is described in Sean Parent's value semantics talk.

    0 讨论(0)
  • 2020-11-30 21:14

    You got very close. I added a few bits because they're handy

    class ParameterBase
    {
    public:
        virtual ~ParameterBase() {}
        template<class T> const T& get() const; //to be implimented after Parameter
        template<class T, class U> void setValue(const U& rhs); //to be implimented after Parameter
    };
    
    template <typename T>
    class Parameter : public ParameterBase
    {
    public:
        Parameter(const T& rhs) :value(rhs) {}
        const T& get() const {return value;}
        void setValue(const T& rhs) {value=rhs;}    
    private:
        T value;
    };
    
    //Here's the trick: dynamic_cast rather than virtual
    template<class T> const T& ParameterBase::get() const
    { return dynamic_cast<const Parameter<T>&>(*this).get(); }
    template<class T, class U> void ParameterBase::setValue(const U& rhs)
    { return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); }
    
    class Diagram
    {
    public:
        std::vector<ParameterBase*> v;
        int type;
    };
    

    Diagram can then do stuff like these:

    Parameter<std::string> p1("Hello");
    v.push_back(&p1);
    std::cout << v[0]->get<std::string>(); //read the string
    v[0]->set<std::string>("BANANA"); //set the string to something else
    v[0]->get<int>(); //throws a std::bad_cast exception
    

    It looks like your intent is to store resource-owning pointers in the vector. If so, be careful to make Diagram have the correct destructor, and make it non-copy-constructable, and non-copy-assignable.

    0 讨论(0)
提交回复
热议问题