F-bounded polymorphism?

G

Gina Yarmel

I am writing an application that has two classes that I would like to
treat like vectors (in the mathematical sense); I'd like * and +
operations for scalar multiplication. I also need the std::vector
interface for its dynamic allocation. So, I inherit from std::vector,
and I want to write a function

template<typename S, typename T>
T operator*(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

My problem is that this grabs calls for T=<some enum type>. I've
thought of two ways I could prevent this disaster, none of which are
legal C++.

1. I want some sort of bounded polymorphism where T must be a subtype
of vector<S>.
2. I want some sort of "thistype" identifier, so that I can write the
above definition, with "T" replaced by "thistype", and the definition
placed in some "myvec<T>" class that my classes inherit from. in
inherited classes, "thistype" is read at "typeof(*this)".

I suppose I could also rewrite the definition for each class, or use a
macro, but isn't avoiding those the motivation for templates?
 
D

David Turner

Hi

Gina Yarmel said:
I am writing an application that has two classes that I would like to
treat like vectors (in the mathematical sense); I'd like * and +
operations for scalar multiplication. I also need the std::vector
interface for its dynamic allocation. So, I inherit from std::vector,
and I want to write a function

template<typename S, typename T>
T operator*(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

My problem is that this grabs calls for T=<some enum type>. I've
thought of two ways I could prevent this disaster, none of which are
legal C++.

1. I want some sort of bounded polymorphism where T must be a subtype
of vector<S>.

Such a thing is not available in the standard. You might try the boost
Concept Check library. However, what's wrong with

template<typename S>
vector said:
2. I want some sort of "thistype" identifier, so that I can write the
above definition, with "T" replaced by "thistype", and the definition
placed in some "myvec<T>" class that my classes inherit from. in
inherited classes, "thistype" is read at "typeof(*this)".

Which *this are you talking about? Derived classes know about their type;
base classes cannot (for obvious reasons) know about their derived types.
That is, unless the base class is templatized on the derived class, but
that's another story :). I'm not sure what you want here.

Regards
David Turner
 
G

Glen Low

template said:
T operator*(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

My problem is that this grabs calls for T=<some enum type>. I've
thought of two ways I could prevent this disaster, none of which are
legal C++.

1. I want some sort of bounded polymorphism where T must be a subtype
of vector<S>.

Why not just
template <typename S> T operator* (const S& op1, const vector <S>& op)
?

Or you can use the "curiously recursive" inheritance pattern like I
did for my library "macstl" (ref my site URL).

template <typename T> class base;
template <typename S> T operator* (const S& op1, const base <T>& op);

and say you have types A, B, C you want to participate in this:

class A: public base <A> { ... };
template <typename X> class B: public base <B <X> > { ... };
template <typename X, typename Y> class C: public base <C <X, Y> > {
.... };

Thus, base acts like a marker interface to limit the operator* to
affect only things that inherit from base. The reason you may need
base <T> instead of just a plain class base is that you may need to
expose or use the T in the base code. It is "compile-time
polymorphism".

Or you can always use std::valarray or the Blitz classes which
basically declare operators on arrays and/or vectors.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
 
P

Peter A. Kerzum

(e-mail address removed) (Gina Yarmel) wrote in message
I am writing an application that has two classes that I would like to
treat like vectors (in the mathematical sense); I'd like * and +
operations for scalar multiplication. I also need the std::vector
interface for its dynamic allocation. So, I inherit from std::vector,
and I want to write a function

template<typename S, typename T>
T operator*(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

My problem is that this grabs calls for T=<some enum type>. I've
thought of two ways I could prevent this disaster, none of which are
legal C++.

1. I want some sort of bounded polymorphism where T must be a subtype
of vector<S>.
2. I want some sort of "thistype" identifier, so that I can write the
above definition, with "T" replaced by "thistype", and the definition
placed in some "myvec<T>" class that my classes inherit from. in
inherited classes, "thistype" is read at "typeof(*this)".

I suppose I could also rewrite the definition for each class, or use a
macro, but isn't avoiding those the motivation for templates?

I don't apprehend your intention but in any case writing such a
template is a bad idea:
1. It catches all multiplication with user types
2. It's implementation isn't generic enough to handle all the
multiplication
(in fact it's not capable of T*S vs S*T)

Though there are ways to check inherritance relations at compile-time
(see SUPERSUBCLASS at moderncppdesign.com, Loki library)
as far as I understand you really want to multiply a scalar value
with 2 kinds of vectors of scalar values. Is it ? Let's try

template<class S> class Vec1 {...} // first vector
template<class S> class Vec2 {...} // second vector

// your implementation renamed
template<typename S, typename T>
T mul_scal_vec(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

// operators
template<class S>
Vec1 operator*(const S& scalar,const Vec1& vector)
{ return mul_scal_vec(scalar,vector); }

template<class S>
Vec2 operator*(const S& scalar,const Vec2& vector)
{ return mul_scal_vec(scalar,vector); }

These operators still catch enum but does it still bother you ?
 
J

Joshua Lehrer

I am writing an application that has two classes that I would like to
treat like vectors (in the mathematical sense); I'd like * and +
operations for scalar multiplication. I also need the std::vector
interface for its dynamic allocation. So, I inherit from std::vector,
and I want to write a function

template<typename S, typename T>
T operator*(const S & op1, const T & op2) {
T ans(op2);
for(typename T::iterator i = ans.begin(); i != ans.end(); ++i) {
i = op1 * *i;
}
return ans;
}

My problem is that this grabs calls for T=<some enum type>. I've
thought of two ways I could prevent this disaster, none of which are
legal C++.

you can use restricted templates:

template <bool> struct restricted;
template <> struct restricted<true> { typedef void type; };

template <typename T> void func(
const T& arg,
typename restricted< boost::is_fundamental< T >::value >::type* =0
);

func(3); //ok
func(std::string("not_ok"));

the templated function "func" will be discarded from the overload set
if the test "boost::is_fundamental<T>::value" is false.

joshua lehrer
factset research systems
NYSE:FDS
 
G

Gina Yarmel

David Turner said:
However, what's wrong with

template<typename S>
vector<S> operator *(const S& sca, const vector<S>& vec) { ... }?

It returns a vector, whereas I need a subclass. Consider two classes,
vectors with color, and vectors with smell. When I multiply either, I
should keep their additional characteristics.
Which *this are you talking about? Derived classes know about their type;
base classes cannot (for obvious reasons) know about their derived types.
That is, unless the base class is templatized on the derived class, but
that's another story :). I'm not sure what you want here.

I would want a keyword thistype such that

#include <iostream>

class base {
public:
void some_func() const {
std::cout << typeid(thistype).name();
}
};

class derived : public base {};

int main() {
base foo;
foo.some_func();
}

prints "derived". If this were the case, then I could write

template<typename T>
class myvec : public std::vector<T> {
public:
thistype multiply(T a, thistype b) {/**/}
};

class color_vec : public myvec<int> {};
class smelly_vec : public myvec<int> {};
 
L

llewelly

It returns a vector, whereas I need a subclass. Consider two classes,
vectors with color, and vectors with smell. When I multiply either, I
should keep their additional characteristics.



I would want a keyword thistype such that

#include <iostream>

class base {
public:
void some_func() const {
std::cout << typeid(thistype).name();


Why is typeid(*this).name() insufficient?
}
};

class derived : public base {};

int main() {
base foo;
foo.some_func();
}

prints "derived". If this were the case, then I could write

But that's nonsense. foo is of type base, not derived.

If you make foo of type derived, typeid(*this).name() will do more or
less what you want, modulo the customary variations in the output
of typeid().name() .

[snip]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,813
Members
47,357
Latest member
sitele8746

Latest Threads

Top