Topic: C++ casts and rvalue references
Author: jdennett@acm.org (James Dennett)
Date: Tue, 25 Jul 2006 05:31:18 GMT Raw View
Richard Smith wrote:
> Ben Hutchings wrote:
>> A dynamic_cast function would not be able to access protected and
>> private inheritances that its caller could.
>
> Why not? Clearly dynamic_cast can't be implemented without compiler
> support (or at least detailed knowledge of the ABI), and given this, I
> don't see why it shouldn't be able to handle non-public inheritance.
>
> For example, on a platform using the Itanium C++ ABI (as used by gcc),
> all it needs to do is call down to the internal __dynamic_cast
> function.
Implementing dynamic_cast to ignore access control is trivial.
But it shouldn't be done. It's more useful that dynamic_cast
should respect access control.
I can accept abstractly that there might be a situation where
a dynamic_cast which ignored access control could be useful,
but I've never seen such a case. If we had such a thing I'd
want it to have a different name: how about something elegant
like dynamic_access_control_bypassing_cast?
-- James
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Tue, 25 Jul 2006 09:33:21 CST Raw View
James Dennett wrote:
> Richard Smith wrote:
> > Ben Hutchings wrote:
> >> A dynamic_cast function would not be able to access protected and
> >> private inheritances that its caller could.
> >
> > Why not? Clearly dynamic_cast can't be implemented without compiler
> > support (or at least detailed knowledge of the ABI), and given this, I
> > don't see why it shouldn't be able to handle non-public inheritance.
> >
> > For example, on a platform using the Itanium C++ ABI (as used by gcc),
> > all it needs to do is call down to the internal __dynamic_cast
> > function.
>
> Implementing dynamic_cast to ignore access control is trivial.
> But it shouldn't be done.
I agree. I think I had misunderstood the point Ben Hutchings was
making. His point was that if dynamic_cast is an ordinary function,
either it can be made to bypass all access control (which as you say
would be a bad idea), or it has to respect access control meaning that
within the implementation of a class you cannot dynamic_cast from a
private base. And whilst that's probably an unusual thing to do, it
certainly is done in existing code -- I've just found an example in
some of my own code.
If the aim is simply to allow the dynamic_cast syntax to be used in
generic code on raw pointers or smart pointers, perhaps the solution is
not to make it a function, but to allow it to be overloaded as an
operator.
// Example of dynamic_cast operator at namespace scope
template <class T, class U>
T operator dynamic_cast( tr1::shared_ptr<U> const& src ) {
return tr1::dynamic_pointer_cast< typename T::element_type >(src);
}
// Example of dynamic_cast operator at class scope
template <class T>
class my_ptr {
public:
typedef T element_type;
T* get() const { return m_ptr; }
template <class U>
U operator dynamic_cast() const {
return U( dynamic_cast< typename U::element_type* >( m_ptr ) );
}
private:
T* m_ptr;
};
In fact, this has a second benefit over making dynamic_cast an ordinary
function: argument dependent look-up can occur. As dymamic_cast needs
the result type explicitly specifying using the template argument
syntax, ADL would not occur on a function. By leaving it as an
operator (though allowing it to be overloaded), ADL can be allowed into
the namespace of argument (and perhaps result) types, meaning that
overloads of dynamic_cast need not be placed in the global namespace.
The question is, do the benefits (better use in generic code; improved
support for smart pointers and references) outweight the (relatively
small) extra complexity required in the standard? My view is that it
does.
--
Richard Smith
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Sat, 22 Jul 2006 16:26:43 GMT Raw View
Richard Smith <richard@ex-parrot.com> wrote:
> TR1 includes several of its own cast functions that are styled to look
> like C++'s built-in cast operators, e.g.
>
> template <class T, class U>
> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const& r );
>
> It seems to me that a more natural syntax (though not permitted in
> current standard) would be to simply overload the dyanamic_cast
> operator for shared_ptr:
>
> template <class T, class U>
> boost::enable_if< is_a_shared_ptr<T>, T >
> dynamic_cast( std::tr1::shared_ptr<U> const& r );
>
> Of course, this isn't legal in the current language because
> dynamic_cast isn't a function and so can't be overloaded. As far as I
> can see, the only reason for it not to be a function is without rvalue
> references, there is no way to declare functions that have precisely
> the lvalue/rvalue semantics that the standard requires.
<snip>
A dynamic_cast function would not be able to access protected and
private inheritances that its caller could.
Ben.
--
Ben Hutchings -- ben@decadentplace.org.uk shortened to ben@decadent.org.uk
If you've signed my GPG key, please send a signature on and to the new uid.
If you seem to know what you are doing, you'll be given more to do.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Mon, 24 Jul 2006 09:01:01 CST Raw View
Ben Hutchings wrote:
>
> A dynamic_cast function would not be able to access protected and
> private inheritances that its caller could.
Why not? Clearly dynamic_cast can't be implemented without compiler
support (or at least detailed knowledge of the ABI), and given this, I
don't see why it shouldn't be able to handle non-public inheritance.
For example, on a platform using the Itanium C++ ABI (as used by gcc),
all it needs to do is call down to the internal __dynamic_cast
function.
--
Richard Smith
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: musiphil@bawi.org (Seungbeom Kim)
Date: Wed, 19 Jul 2006 02:20:00 GMT Raw View
Richard Smith wrote:
> TR1 includes several of its own cast functions that are styled to look
> like C++'s built-in cast operators, e.g.
>
> template <class T, class U>
> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const& r );
>
> It seems to me that a more natural syntax (though not permitted in
> current standard) would be to simply overload the dyanamic_cast
> operator for shared_ptr:
>
> template <class T, class U>
> boost::enable_if< is_a_shared_ptr<T>, T >
> dynamic_cast( std::tr1::shared_ptr<U> const& r );
>
> Of course, this isn't legal in the current language because
> dynamic_cast isn't a function and so can't be overloaded.
Not because it is not a function;
neither 'new' nor 'delete' is a function, but both are overloadable. :)
--
Seungbeom Kim
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Tue, 18 Jul 2006 10:15:33 CST Raw View
TR1 includes several of its own cast functions that are styled to look
like C++'s built-in cast operators, e.g.
template <class T, class U>
shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const& r );
It seems to me that a more natural syntax (though not permitted in
current standard) would be to simply overload the dyanamic_cast
operator for shared_ptr:
template <class T, class U>
boost::enable_if< is_a_shared_ptr<T>, T >
dynamic_cast( std::tr1::shared_ptr<U> const& r );
Of course, this isn't legal in the current language because
dynamic_cast isn't a function and so can't be overloaded. As far as I
can see, the only reason for it not to be a function is without rvalue
references, there is no way to declare functions that have precisely
the lvalue/rvalue semantics that the standard requires. With rvalue
references, this is now possible, so I can write
template <class T, class U>
where std::True< std::tr1::is_pointer<T>::value >
T dynamic_cast( U* ) throw();
template <class T, class U>
where std::True< is_lvalue_reference<T>::value >
T dynamic_cast( U& ) throw( std::bad_cast );
template <class T, class U>
where std::True< is_rvalue_reference<T>::value >
T dynamic_cast( U&& ) throw( std::bad_cast );
. and then <memory> can add an overload for shared_ptr. In terms of
the ability to write generic code, having the same syntax for casting
native pointers and "smart" pointers has to be a good thing.
So far as I can see, this is a pure extension in that any
currently-conforming program will continue to be valid (assuming these
functions are in scope without requiring a #include, much as ::operator
new is).
This will also allow users to take the address of the dynamic_cast
functions meaning that it can be used in (say) a tr1::bind expression
without needing a proxy function to be written.
Are there any plans to allow something like this?
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 18 Jul 2006 16:30:10 GMT Raw View
Richard Smith posted:
> As far as I
> can see, the only reason for it not to be a function is without rvalue
> references, there is no way to declare functions that have precisely
> the lvalue/rvalue semantics that the standard requires.
Boost's implicit_casts works perfectly as regards L-value's and R-value's.
template <typename T>
inline T implicit_cast (typename mpl::identity<T>::type x) {
return x;
}
I haven't a clue how it works though...
--
Frederick Gotham
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Tue, 18 Jul 2006 12:05:27 CST Raw View
Frederick Gotham wrote:
> Richard Smith posted:
>
> > As far as I
> > can see, the only reason for it not to be a function is without rvalue
> > references, there is no way to declare functions that have precisely
> > the lvalue/rvalue semantics that the standard requires.
>
>
> Boost's implicit_casts works perfectly as regards L-value's and R-value's.
>
> template <typename T>
> inline T implicit_cast (typename mpl::identity<T>::type x) {
> return x;
> }
But that works because of the specific properties of implicit casts.
Specifically, because the implicit conversion actually happens on the
argument of the function call when converting to the parameter type,
rather than in the function. This works because implicit_cast does not
need to use template argument deduction.
For any more ambitious sort of cast (e.g. explicit_cast, or any of the
standard ones), I can't see how you can avoid needing template argument
deduction, and so I can't see how you can make this trick work. But
maybe I'm missing something.
--
Richard Smith
---
[ 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.comeaucomputing.com/csc/faq.html ]