C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

template for all derived classes

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Tony
Guest





PostPosted: Tue Jan 20, 2004 10:59 pm    Post subject: template for all derived classes Reply with quote



Hi, C++ Gurus,

I am considering the following problem.

struct Scalar {
double s;
Scalar(double d):s(d) { }
};

struct Length:public Scalar {
static double convertor;
Length(double l):Scalar(l) { }
};

struct Area:public Scalar {
static double convertor;
Area(double l):Scalar(l) { }
};

template<class S> S operator+(const S &s1, const S &s2)
{
S s(s1.s + s2.s);
return s;
}

In the template, I want S to be derived class of Scalar, nothing else.
How can I do it?

If I allow S to be other types, operator+ may be called for some types
accidently. This is what I want to avoid.

Regards
Tony

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





PostPosted: Wed Jan 21, 2004 9:16 am    Post subject: Re: template for all derived classes Reply with quote



"Tony" <tongru_huo (AT) netzero (DOT) com> wrote

Quote:
Hi, C++ Gurus,

I am considering the following problem.

struct Scalar {
double s;
Scalar(double d):s(d) { }
};

struct Length:public Scalar {
static double convertor;
Length(double l):Scalar(l) { }
};

struct Area:public Scalar {
static double convertor;
Area(double l):Scalar(l) { }
};

template<class S> S operator+(const S &s1, const S &s2)
{
S s(s1.s + s2.s);
return s;
}

In the template, I want S to be derived class of Scalar, nothing
else.
How can I do it?


There are at least two ways. If there are no other overloads of
operator+ in the picture (I'm being intentionally vague), you can do a
static assert within the body of the function:

template<class S> S operator+(const S &s1, const S &s2)
{
BOOST_STATIC_ASSERT(( is_base_and_derived<Scalar, S>::value ));
S s(s1.s + s2.s);
return s;
}

This causes a compile-time error is operator+ is called with S not a
derived class of Scalar. (See
http://www.boost.org/libs/static_assert/static_assert.htm and
http://www.boost.org/libs/type_traits/index.htm for documentation.)

If there are other overloads of operator+ around, you can use the
enable_if utility described in the June 2003 issue of CUJ, and soon to
be part of boost:

template<class S>
typename boost::enable_if< boost::is_base_and_derived S>::type
operator+(const S &s1, const S &s2);

This prevents overload resolution from selecting the above overload of
operator+ unless S is derived from Scalar. For documentation, see CUJ,
http://www.esva.net/~beman/boost_1_31_0_rc1.zip, or soon,
http://www.boost.org/libs/utility/enable_if.html.

HTH

Jonathan




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

Back to top
Mario
Guest





PostPosted: Wed Jan 21, 2004 3:44 pm    Post subject: Re: template for all derived classes Reply with quote



[email]tongru_huo (AT) netzero (DOT) com[/email] (Tony) wrote in message >
Quote:
template<class S> S operator+(const S &s1, const S &s2)
{
S s(s1.s + s2.s);
return s;
}

In the template, I want S to be derived class of Scalar, nothing else.
How can I do it?


Hi,
you can use the boost library

Use "::boost::is_base_and_derived<T,U>::value" from boost/type_traits.hpp
to get the relation between the classes and use "mpl::if_< >" from boosts
mpl library to make a decision at compile time. You can get a structure
failing to compile if the relations are not valid.

hth
Mario

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

Back to top
Dan McLeran
Guest





PostPosted: Wed Jan 21, 2004 7:50 pm    Post subject: Re: template for all derived classes Reply with quote

Quote:
In the template, I want S to be derived class of Scalar, nothing else.
How can I do it?

If I allow S to be other types, operator+ may be called for some types
accidently. This is what I want to avoid.


See boost::type_traits,
http://www.boost.org/libs/type_traits/index.htm, and
boost::static_assert,
http://www.boost.org/libs/static_assert/static_assert.htm. Here is an
example:

#include <iostream>
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

using std::cout;
using std::endl;

struct Thing
{
};

struct Something : public Thing
{
void say() const
{
cout<<"I am a thing!"< }
};

struct NotAThing
{
void say() const
{
cout<<"I am not a thing!"< }
};

template void SaySomething(U const& arg)
{
using namespace boost;
BOOST_STATIC_ASSERT((is_base_and_derived<Thing,U>::value));
arg.say();
}

int main()
{
Something a;
NotAThing b;

SaySomething(a);
//SaySomething(b);//will cause a compiler error

return 0;
}

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

Back to top
Peter Dimov
Guest





PostPosted: Fri Jan 23, 2004 10:26 am    Post subject: Re: template for all derived classes Reply with quote

[email]tongru_huo (AT) netzero (DOT) com[/email] (Tony) wrote in message news:<9396fe12.0401200902.645a38a4 (AT) posting (DOT) google.com>...
Quote:
Hi, C++ Gurus,

I am considering the following problem.

struct Scalar {
double s;
Scalar(double d):s(d) { }
};

struct Length:public Scalar {
static double convertor;
Length(double l):Scalar(l) { }
};

struct Area:public Scalar {
static double convertor;
Area(double l):Scalar(l) { }
};

template<class S> S operator+(const S &s1, const S &s2)
{
S s(s1.s + s2.s);
return s;
}

In the template, I want S to be derived class of Scalar, nothing else.
How can I do it?

Without repeating what others already said, here's one more possibility:

template<class Derived> struct Scalar {
double s;
Scalar(double d):s(d) { }
};

struct Length:public Scalar<Length> {
static double convertor;
Length(double l):Scalar<Length>(l) { }
};

struct Area:public Scalar<Area> {
static double convertor;
Area(double l):Scalar<Area>(l) { }
};

template<class S> Scalar<S> operator+(const Scalar<S> &s1, const Scalar<S> &s2)
{
Scalar<S> s(s1.s + s2.s);
return s;
}

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

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.