Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old July 19th, 2005, 05:18 PM
Gina Yarmel
Guest
 
Posts: n/a
Default F-bounded polymorphism?

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?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #2  
Old July 19th, 2005, 05:18 PM
David Turner
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

Hi

"Gina Yarmel" <taintedwheat@yahoo.com> wrote in message
news:e4241c19.0308111332.13dba1dd@posting.google.c om...[color=blue]
> 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>.[/color]

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<S> operator *(const S& sca, const vector<S>& vec) { ... }?
[color=blue]
> 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)".[/color]

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



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #3  
Old July 19th, 2005, 05:18 PM
Glen Low
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

> template<typename S, typename T>[color=blue]
> 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>.[/color]

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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #4  
Old July 19th, 2005, 05:19 PM
Peter A. Kerzum
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

taintedwheat@yahoo.com (Gina Yarmel) wrote in message
news:<e4241c19.0308111332.13dba1dd@posting.google. com>...[color=blue]
> 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?[/color]

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 ?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #5  
Old July 19th, 2005, 05:20 PM
Joshua Lehrer
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

taintedwheat@yahoo.com (Gina Yarmel) wrote in message news:<e4241c19.0308111332.13dba1dd@posting.google. com>...[color=blue]
> 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++.
>[/color]

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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #6  
Old July 19th, 2005, 05:23 PM
Gina Yarmel
Guest
 
Posts: n/a
Default F-bounded polymorphism?

"David Turner" <david@firepro.co.za> wrote[color=blue]
> However, what's wrong with
>
> template<typename S>
> vector<S> operator *(const S& sca, const vector<S>& vec) { ... }?[/color]

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.
[color=blue]
> 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[/color]
[color=blue]
> that's another story :-). I'm not sure what you want here.[/color]

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> {};

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #7  
Old July 19th, 2005, 05:23 PM
Glen Low
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

> you can use restricted templates:

You can also do the same sort of thing with return types in gcc 3.3
(earlier versions have limited support). The technique is based on
SFINAE and here's good treatise on it:

http://m17n.org/martin/writings/temp...nstraints.html

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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
  #8  
Old July 19th, 2005, 05:29 PM
llewelly
Guest
 
Posts: n/a
Default Re: F-bounded polymorphism?

taintedwheat@yahoo.com (Gina Yarmel) writes:
[color=blue]
> "David Turner" <david@firepro.co.za> wrote[color=green]
> > However, what's wrong with
> >
> > template<typename S>
> > vector<S> operator *(const S& sca, const vector<S>& vec) { ... }?[/color]
>
> 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.
>[color=green]
> > 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[/color]
>[color=green]
> > that's another story :-). I'm not sure what you want here.[/color]
>
> I would want a keyword thistype such that
>
> #include <iostream>
>
> class base {
> public:
> void some_func() const {
> std::cout << typeid(thistype).name();[/color]


Why is typeid(*this).name() insufficient?
[color=blue]
> }
> };
>
> class derived : public base {};
>
> int main() {
> base foo;
> foo.some_func();
> }
>
> prints "derived". If this were the case, then I could write[/color]

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]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles