3

Context

I would like to create a vector of Attribute variables, T marking any other class. A sample:

template<typename T>
class Attribute{
public:
    string name;
    T value;
    Attribute(){  }
    Attribute(string n, T val){ name = n; value = val; }
    string getName(){ return name; }
    string setName(string n){ name = n; }
    T getAttr(){ return value; }
    void setAttr(T v){ value = v; }
};

Now, from this I would like to create a vector, which can hold different kind of Attributes, like Attribute\ and Attribute\. Since you have to give to the template used for Attribute when creating the vector, I figured to use an abstract base class, or Interface.

The real problem

I have an interface, called AttributeInterface, which defines the possible methods for an Attribute, but I cannot define the getter and setter methods for the Attribute.value variable, as I don't know their signature before using the template. If I use a template with AttributeInterface, then I'm back at the problem mentioned on the previous block.

class AttributeInterface{
public:
    virtual string getName();
    virtual string setName();
    virtual ?? getAttr();
    virtual void setAttr(?? v);
};
template<typename T>
class Attribute: public AttributeInterface{
public:
    string name;
    T value;
    Attribute(){  }
    Attribute(string name, T val){ this.name = name; value = val; }
    string getName(){ return name; }
    string setName(string n){ name = n; }
    T getAttr(){ return value; }
    void setAttr(T v){ value = v; }
};

And this would be the expected usage:

std::vector <??> vec;
// Or something along the lines of std::vector<AttributeInterface*> vec;
vec.push_back(new Attribute<float>("a", 1.0));
vec.push_back(new Attribute<int>("a", 10));

For reference, in a dynamically typed language like Python, the use case would be simply

class Attribute:
    ...
    def get(self):
        return self.value

    def set(self,v):
        self.value = v

l = []
l.append(Attribute('a',1.5))
l.append(Attribute('a',"foo"))
for i in l:
    print(i.get())

Is my original idea even feasible in c++? Or is there any easier/better method to reach the behavior described with the Python example?

Thanks in advance.

Brabulla
  • 75
  • 6
  • You can't have a `vector` to hold derived types because the elements are stored by-value. You will need to use `vector` instead, and manage the memory yourself, see here: http://stackoverflow.com/questions/8777724/store-derived-class-objects-in-base-class-variables – Dai Dec 05 '16 at 23:40
  • Using strongly-typed subclasses means you will need to cast the result from a `SomeBaseType*` to a `SomeDerivedType*` when you retrieve from the vector. – Dai Dec 05 '16 at 23:42
  • 1
    What is the actual problem (i.e. the business problem that you're being paid to solve)? Type information is lost in your example: a consumer has no way of knowing if a an `Attribute` instance contains an `int` or something else - so how do you plan to consume the code you're writing?What is the domain problem this solves? – Dai Dec 05 '16 at 23:45
  • `Attribute` and `Attribute` are different types so you can't store both in same vector. Can you use std::any/boost::any as the Attribute value type instead of template? – TheMagician Dec 05 '16 at 23:45
  • @Dai Thanks for the pointer error, going to edit the original question to use the pointer of the base class. For the second part, when retrieving I still wouldn't know what type to cast to, as I would like to use the classes through an interface. For the third part, the business problem: I have to implement something alike reflection. I have to store what attributes a class has, and parameters linked to those attributes. Also, I have to store the getter/setter functions to those attributes, to use with GUI callbacks. – Brabulla Dec 05 '16 at 23:47
  • @TheMagician I'm not yet familiar with std::any, but I would like to avoid using boost. Going to look into it – Brabulla Dec 05 '16 at 23:53
  • @Dai no raw owning pointers, thanks! `std::unique_ptr` will do just fine ;) – Quentin Dec 06 '16 at 00:08

0 Answers0