Topic: explicit cast (was C++0x)
Author: Sean Parent <sparent@Adobe.COM>
Date: Sat, 5 May 2001 12:14:47 GMT Raw View
An earlier post got me thinking about about the need for "explicit" for cast
operators on classes. The normal recommendation of just using a member
function (such as "as()" isn't particularly helpful when you are trying to
plug the class into generic functions - but you don't want the cast to
happen implicitly.
I came up with the following solution:
//file: gen_explicit_cast.h
template <typename lht, typename rht>
inline lht explicit_cast(const rht& rhs)
{ return static_cast<lht>(rhs); }
//---
You can use this template function just as you would static_cast:
int foo = explicit_cast<double>(10);
But you can also specialize it for a particular class:
//--
class sample_t
{
public:
explicit sample_t(int x) : fX(x) { }
friend double explicit_cast<double>(const sample_t& rhs);
private:
int fX;
};
template <>
inline double explicit_cast<double>(const sample_t& rhs)
{ return rhs.fX; }
//--
Now you can write a generic function that will work with this class (or a
similar class) or with anything for which a static cast is allowed. For
example, here is an alternate to std::accumulate.
//--
template <typename lht, class ForwardIterator>
lht sum(ForwardIterator first, ForwardIterator last)
{
lht result(0);
while (first != last)
{
result += explicit_cast<lht>(*first);
++first;
}
return result;
}
//--
Given the above you can write code like the following:
//--
sample_t samplea[] = { sample_t(1), sample_t(3), sample_t(5) };
std::cout << sum<double>(&samplea[0], &samplea[3]) << std::endl;
//--
You even get meaningful error messages (at least out of MWCW 6.1):
sample_t sample(10);
std::cout << explicit_cast<bool>(sample) << std::endl;
Will generate:
Error : illegal explicit conversion from 'const sample_t' to 'bool'
It would be a little spiffier if you could just specialize static_cast<>
then you wouldn't have to rewrite a bunch of existing generic algorithms.
But it seems to solve most of the issues. I've been giving some thought as
to how you would write a runtime_cast<> template that would behave like
dynamic_cast<> but you could specialize it for smart pointers. The
differences between behaviors for T& and T* is tripping me up along with
being able to specialize for any type which is, for example, derived from
auto_ptr<> - anyone want to take a stab at it?
--
Sean Parent
Sr. Engineering Manager
Adobe Workgroup Services
sparent@adobe.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 5 May 2001 23:26:05 GMT Raw View
On Sat, 5 May 2001 12:14:47 GMT, Sean Parent <sparent@Adobe.COM> wrote:
> An earlier post got me thinking about the need for "explicit" for cast
> operators on classes. The normal recommendation of just using a member
> function (such as "as()" isn't particularly helpful when you are trying to
> plug the class into generic functions - but you don't want the cast to
> happen implicitly.
I don't see any problem plugging the class into a well written generic
function.
[snip explicit_cast]
> But you can also specialize it for a particular class:
>
> //--
>
> class sample_t
> {
> public:
> explicit sample_t(int x) : fX(x) { }
double as_double () const { return fX; }
>
> friend double explicit_cast<double>(const sample_t& rhs);
> private:
> int fX;
> };
>
> template <>
> inline double explicit_cast<double>(const sample_t& rhs)
> { return rhs.fX; }
>
> //--
>
> Now you can write a generic function that will work with this class (or a
> similar class) or with anything for which a static cast is allowed. For
> example, here is an alternate to std::accumulate.
>
> //--
>
> template <typename lht, class ForwardIterator>
> lht sum(ForwardIterator first, ForwardIterator last)
> {
> lht result(0);
> while (first != last)
> {
> result += explicit_cast<lht>(*first);
> ++first;
> }
> return result;
> }
>
> //--
>
> Given the above you can write code like the following:
>
> //--
>
> sample_t samplea[] = { sample_t(1), sample_t(3), sample_t(5) };
> std::cout << sum<double>(&samplea[0], &samplea[3]) << std::endl;
>
> //--
struct Adder_sample_t {
double operator() (double a, sample_t const& s) {
return a + s.as_double();
}
};
cout << accumulate(samplea, samplea + 3, 0.0, Adder_sample_t()) << endl;
I don't see any improvement. The standard algorithms are adaptable.
Would you suggest removing transform and adding explicit_cast to copy?
IMHO, this is just a special case substitution for the generality of
the standard algorithms.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]