1

Being new to template programming, I'm getting lost in a structure I'm trying to build.

class Base;

template <typename T>
class Foo : public Base {
protected:
    T mValue;
    std::vector<Base> mFooVector;   // the idea is to have Foo<T> elements
                                    // of several T types

public:
    T value() {
        return mValue;
    }

    void SetValueFromVector() {
        mValue = Transform( mFooVector );
        // to give you an idea of what awaits below
    }

    T Transform( std::vector<Base> ) {
        // Question deals with what I want to do here
    }

    /*...*/
}

class Base{
    // here, how to declare a virtual or template 'value()'
    // that could be instantiated or specialized within Foo?
    // Or should I declare a public 'mValue' of some type?
    // (see below)
};

In Transform I would like to call value() from all elements of 'mFooVector' which can be arranged in various type associations. There would be functions, defined elsewhere, that handle all possible practical cases. But there remains the question of how to call value() or access mValue from objects declared as instances of class Base.

I asked a question yesterday that was only the start of my research - the problem is not the container anymore, since I used polymorphism, but the fact that I need to call the value() function on instances it contains.

EDIT: In case it helps anyone, here is the way I eventually defined by class. I accepted @PiotrNycz 's answer because it led me really close to my goal, but it was not exactly implementing what I needed.

class Base {
public:
   virtual void setValue( &int ) =0;
   virtual void setValue( &float ) =0;
   virtual void setValue( &double ) =0;
}

template <typename T>
class Foo : public Base {
protected:
    T mValue;
    std::vector<Base*> mFooVector;
    T Transform( std::vector<Base*> );
public:

    // this is for use from outside the class
    T value() {
       return mValue;
    }

    void SetValueFromVector() {
       mValue = Transform( mFooVector );
    }

    // the three below are only going to be used within 'Transform'
    void setValue( int& i ) { i = mValue; }
    void setValue( float& f ) { f = (float) mValue; }
    void setValue( double& d ) { d = (double) mValue; }
}

// specialization of Transform
template<>
int Foo<int>::Transform( std::vector<Base*> v )
{
    // here I only use setValue functions
    // if for example I know that first v element is 'float'
    float val;
    v[0]->setValue( val );

    return 3*int(val);
}
// and etc.
Community
  • 1
  • 1
nenj
  • 119
  • 9
  • 1
    You will need a `std::vector` if you want _polymorphism_, otherwise you will incur in _slicing_. – K-ballo Oct 20 '12 at 06:00
  • OK, thanks for this remark. I think my question remains though, if the vector's elements are pointers I still want to apply value() on them. – nenj Oct 20 '12 at 06:02
  • possible duplicate of [How to put different template types into one vector](http://stackoverflow.com/questions/696399/how-to-put-different-template-types-into-one-vector) – jogojapan Oct 20 '12 at 06:04
  • @K-ballo, now that I think of it, it may actually do the trick! I'll restructure my code + take advantage of polymorphism, which I get better now from reading on slicing. – nenj Oct 20 '12 at 06:45

1 Answers1

0

I am assuming you know all your possible value types, let say they are int/float/..., then your base class must be prepared (by pure virtual methods) to do adding to any of the the values types:

class Base {
public:
  virtual ~Base() {}
  virtual void addTo(int& value) = 0;
  virtual void addTo(long& value) = 0;
  virtual void addTo(float& value) = 0;
  virtual void addTo(double& value) = 0;
  // add as many functions as you need and of types you need in your design
  // these types not necessarily must be simple basic types
};

template <class Type> 
class Foo : public Base {
public:
    T Transform( std::vector<Base> ) {
        T retVal = T();
        // Question deals with what I want to do here
        for (auto it = mFooVector.begin(); it != mFooVector.end(); ++i)
          it->addTo(retVal);
        return retVal;
    }
  // and the base interface implementation 
  // (for other types implementation does not need to be some simple)
  virtual void addTo(int& value) { value += mValue; }
  virtual void addTo(long& value) { value += mValue; }
  virtual void addTo(float& value) { value += mValue; }
  virtual void addTo(double& value) { value += mValue; }

private:
  std::vector<std::shared_ptr<Base>> mFooVector;
  // you can here ^^^^^^^^^^^^^^^^^ use simple Base* pointer but must 
  // then define d-tor, copy c-tor and assignment operator
  T mValue;  
};
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • Great. Thank you, this answers my question. I realize however that declaring only `virtual void addTo(T& value) {...}` in the derived class makes it abstract, which is a problem. But I'm not satisfied either by having to implement all types, since then a template class is no use. I'm still looking. – nenj Oct 20 '12 at 19:31
  • @motjordet these methods `addTo` are not for the class where you implement it (so defining `addTo(T&)` makes no sense). These methods are for the any other `Foo` where the given `Foo` will be present in this `Foo::mFooVector`. So you must define `addTo(U&)` for every possible `U`. The problem begins when you do not know every possible `U`. In that case more complicated solution is needed in static language like C++. – PiotrNycz Oct 20 '12 at 21:49