 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Tony Guest
|
Posted: Tue Jan 20, 2004 10:59 pm Post subject: template for all derived classes |
|
|
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
|
Posted: Wed Jan 21, 2004 9:16 am Post subject: Re: template for all derived classes |
|
|
"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
|
Posted: Wed Jan 21, 2004 3:44 pm Post subject: Re: template for all derived classes |
|
|
[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
|
Posted: Wed Jan 21, 2004 7:50 pm Post subject: Re: template for all derived classes |
|
|
| 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
|
Posted: Fri Jan 23, 2004 10:26 am Post subject: Re: template for all derived classes |
|
|
[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 |
|
 |
|
|
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
|
|