views:

46

answers:

5

Hi,

I have an abstract class vertex which represents an n-tuple. The element of the vertex can be of any type: ie, the vertice's components could be of type int, int, float or something. Because the vertex can have an arbitrary number of dimensions, I was thinking of making the class have a component setter like so:

class vertex {
    public:
        template <class T>
        virtual void setComp(int componentnumber, T value) = 0;
};

Of course, C++ doesn't permit virtual function templates. So: how should I be doing this? I also don't know how I should be writing a getter for vertices.

Thanks.

A: 

That's a very weird mix of OO and generic programming. I think you should pick one or the other.

Make the vertex class a template or define a base class for the 'value' parameter and derive custom type handler classes.

Amardeep
A: 

Use polymorphism instead of templates.

Or limit the types you want to pass, and make overloads. And increase maintenance costs.

Implementing these solutions would involve boost::any or boost::variant to save you some time.

Alexandre C.
A: 

Because the vertex can have an arbitrary number of dimensions - wht not make it a

template<size_t N> class vector {

   private:
     boost::any elems[N];
}

then to avoid mixing runtime polymorphism and compile time polymorphism through templates? Or use function overloads for any possible type if their number is limited.

virtual void setComp(int, float) = 0;
virtual void setComp(int, bool) = 0;
Alexander Gessler
I recall having wanted a design like this, and then crying about why didn't I simply made n a member variable...
Alexandre C.
A: 

First of all, I'd ask myself if you really need to access vertex objects polymorphically at runtime. For instance if you need to be able to have a list of vertex* objects with different types (double, int etc.) and access them polymorphically.

It sounds to me like a vertex is a typical case of compile-time polymorphism (i.e. a template <typename CoordinateType> class vertex; template).

Frerich Raabe
I would even go with a simple array<T> or equivalent, but the question was about virtual templates, not whether such design is good.
Alexandre C.
+1  A: 

Well, normally, you're supposed to have the vertex type as a template parameter so it can be stored properly:

template<typename T, size_t NumAxes = 3>
class vertex {
    private:
        T comp[NumAxes];
};

In which case, there's no need for a virtual method since you can just use C++'s typecasting to do the work:

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value) { comp[index] = static_cast<T>(value); }
private:
    T comp[NumAxes];
};

Now, if you want it to be virtual because you want subclasses to be able to mess with things (e.g. log every change in value), you need to define a non-templated function:

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value)
    { _setComp(index, static_cast<T>(value)); }
protected:
    T comp[NumAxes];
    virtual void _setComp(size_t index, T value) 
    { comp[index] = value; }
};

template<typename T, size_t NumAxes = 3>
class logged_vertex: public vertex<T, NumAxes> {
protected:
    virtual void _setComp(size_t index, T value);
};

template<typename T, size_t NumAxes = 3>
void logged_vertex<T, NumAxes>::_setComp(size_t index, T value)
{   cout << "Index " << index << " changed from " << comp[index];
    vertex<T, NumAxes>::_setComp(index, value);
    cout << " to " << comp[index] << endl;
}
Mike DeSimone