Is there any interest in a casting library where you don't need to specify a type of receiver?

Hello all I have my own C++ framework (http://cbear.berlios.de, SVN: http://tools.assembla.com/svn/cbear/trunk/) which has some useful (IMHO) libraries. One of this library is "cast" library (http://tools.assembla.com/cbear/browser/trunk/cbear.berlios.de/cast) which allows you to convert objects without specifying a type: char c; int i; ... // if(c == static_cast<char>(i)) if(c == cast::static_::value(i)) { ... } It is useful when you want to convert an object to a type of another object. And this is also more safe, compare to standard casting, for example in previous code someone can change the type of c to wchar_t, and if you use static_cast, the compiler will not even warn you about incorrect casting. So, you have to manually check all the code. Currently there are several castings: static, reinterpret, const, dynamic, polymorphic (based on Boost.polymorphic_cast), polymorphic_down (based on Boost.polymorphic_downcast), explicit (calls an explicit constructor), safe_reinterpret (compare sizes of converting types), default (returns an object created by default constructor). Thank you. Best regards, Sergey Shandar.

Sergey Shandar wrote:
char c; int i; ... // if(c == static_cast<char>(i)) if(c == cast::static_::value(i)) { ... }
Hi, I too am trying to implement a similar facilities: http://tinyurl.com/ynmf5n `automatic<>::type` can take multiple arguments. BTW, does `polymorphic::ref` work on gcc? I recall I gave up supporting a reference type as target (e.g. `polymorphic::ref`), because gcc-3.4 and 4.1 show a weird compile error. (Though I found a workaround, it was not complete.) Regards, -- Shunsuke Sogame

shunsuke wrote:
Sergey Shandar wrote:
char c; int i; ... // if(c == static_cast<char>(i)) if(c == cast::static_::value(i)) { ... }
Hi, I too am trying to implement a similar facilities: http://tinyurl.com/ynmf5n `automatic<>::type` can take multiple arguments. BTW, does `polymorphic::ref` work on gcc? I recall I gave up supporting a reference type as target (e.g. `polymorphic::ref`), because gcc-3.4 and 4.1 show a weird compile error. (Though I found a workaround, it was not complete.)
Regards,
References work on gcc-3.4.5 (mingw-special). I have not tried 4.X.X. See the test: http://tools.assembla.com/cbear/browser/trunk/cbear.berlios.de/cast/test.cpp. What's wrong with GCC?

Sergey Shandar wrote:
References work on gcc-3.4.5 (mingw-special). I have not tried 4.X.X. See the test: http://tools.assembla.com/cbear/browser/trunk/cbear.berlios.de/cast/test.cpp.
What's wrong with GCC?
You've found that workaround. :-) Yes, gcc requires a named return value. Well, my library contains function adaptors. While adapting, here's what happens internally: template<class X> X const & pass_through_some_adaptor(X const & x) { return x; } D & d = pass_through_some_adaptor(polymorphic_down::ref(b)); // doesn't compile on gcc. Therefore, I gave up. Your library might not be affected, though. Regards, -- Shunsuke Sogame

shunsuke wrote:
Sergey Shandar wrote:
References work on gcc-3.4.5 (mingw-special). I have not tried 4.X.X. See the test: http://tools.assembla.com/cbear/browser/trunk/cbear.berlios.de/cast/test.cpp.
What's wrong with GCC?
You've found that workaround. :-)
Only now. The first two workarounds were not really workarounds. 1. This one is unsafe to use. operator MyClass const &() const { return *this; } In case: MyClass const &x = MyClass(); 2. This one is not really fixing the problem. MyClass const t = MyClass(); MyClass const &x = t; 3. I found this one today: template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
Yes, gcc requires a named return value.
Yes, it tries to use user-defined conversion when converts rvalue to a reference on a constant. I've sent a bug report http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34023
Well, my library contains function adaptors. While adapting, here's what happens internally:
template<class X> X const & pass_through_some_adaptor(X const & x) { return x; }
D & d = pass_through_some_adaptor(polymorphic_down::ref(b)); // doesn't compile on gcc. Therefore, I gave up.
Try workaround # 3. It may help. Best regards, Sergey Shandar.

On Nov 9, 2007 2:06 AM, Sergey Shandar <sergey@comrades.id.au> wrote:
[...] 3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
Wow! Does this really work? You can really apply SFINAE to conversion opreators by (ab)using the exception specification? Is this only a gcc thing or is it "by the standard"? If the latter, boost::enable_if documents might need to be updated :) -- gpd

Giovanni Piero Deretta wrote:
Wow! Does this really work? You can really apply SFINAE to conversion opreators by (ab)using the exception specification? Is this only a gcc thing or is it "by the standard"?
It works on GCC and solves the particular problem, I don't know much about other compilers and "by the standard". It has to be checked if we want to use it in other cases.
If the latter, boost::enable_if documents might need to be updated :)
Yes, may be some extensions to the boost::enable_if library: namespace boost { namespace detail { class never_throw { }; } } #define BOOST_ENABLE_IF(...) throw (typename ::boost::enable_if< __VA_ARGS__, ::boost::detail::never_throw>::type) And using: template <class T> T foo(T t) BOOST_ENABLE_IF(boost::is_arithmetic<T>) { ... } etc.

Sergey Shandar wrote:
3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
You've solved the millenium problem! :-) gcc3.4.5 and 4.1.2 seem to work fine. Thanks! -- Shunsuke Sogame

shunsuke wrote:
Sergey Shandar wrote:
3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
You've solved the millenium problem! :-)
The solution will bring a lot of other problems in other areas. We will see, shortly :-)

shunsuke wrote:
Sergey Shandar wrote:
3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
You've solved the millenium problem! :-)
gcc3.4.5 and 4.1.2 seem to work fine. Thanks!
Right, here is the new problem: If you specify at least one throw type (we do) then you have to specify all possible exceptions for the function! template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *) throw(::std::exception) throw(::MyLibrary::exception) throw( what else? )

Microsoft compiler doesn't fully support "Exception Specifications". The details are below. If you use this feature, it will not be portable code. -Sid Sacek This is from MSDN: ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclang/html/4d3276df-6f31-4c7f-8cab-b9d2d003a629.htm Visual C++ departs from the ANSI Standard in its implementation of exception specifications. The following table summarizes the Visual C++ implementation of exception specifications: Exception specification Meaning throw() The function does not throw an exception. However, if an exception is thrown out of a function marked throw(), the Visual C++ compiler will not call unexpected (see unexpected (CRT) and unexpected (<exception>) for more information). If a function is marked with throw(), the Visual C++ compiler will assume that the function does not throw C++ exceptions and generated code accordingly. Due to code optimizations that maybe performed by the C++ compiler (based on the assumption that the function does not throw any C++ exceptions) if function does throw an exception, the program may not execute correctly. throw(...) The function can throw an exception. throw(type) The function can throw an exception of type type. However, in Visual C++ .NET, this is interpreted as throw(...). See Function Exception Specifiers. -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Sergey Shandar Sent: Saturday, November 10, 2007 7:19 AM To: boost@lists.boost.org Subject: Re: [boost] Is there any interest in a casting library where you don't need to specify a type of receiver? shunsuke wrote:
Sergey Shandar wrote:
3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
You've solved the millenium problem! :-)
gcc3.4.5 and 4.1.2 seem to work fine. Thanks!
Right, here is the new problem: If you specify at least one throw type (we do) then you have to specify all possible exceptions for the function! template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *) throw(::std::exception) throw(::MyLibrary::exception) throw( what else? ) _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Sid Sacek wrote:
Microsoft compiler doesn't fully support "Exception Specifications". The details are below. If you use this feature, it will not be portable code. -Sid Sacek
This is from MSDN:
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclang/html/4d3276df-6f31-4c7f-8cab-b9d2d003a629.htm
Oh, we are discussing the bug fix for GCC. Visual C++ 8.0 doesn't have these problems. Actually, you can use SFINAE in throw() in VC++ as well and it has less problems than GCC.

shunsuke wrote:
Sergey Shandar wrote:
3. I found this one today:
template<class T> operator T &() const throw(typename ::boost::disable_if< ::boost::is_same<T, MyClass const> >::type *)
You've solved the millenium problem! :-)
gcc3.4.5 and 4.1.2 seem to work fine. Thanks!
According to the standard, the code should not work. 14.8.2.2 - All references in the function type of the function template to the corresponding template parameters are replaced by the specified template argument values. If a substitution in a template parameter or in the function type of the function template results in an invalid type, type deduction fails. [Note: *The equivalent substitution in exception specifications is done only when the function is instantiated, at which point a program is ill-formed if the substitution results in an invalid type.*] Type deduction may fail for the following reasons: However, it works on GCC. So, the workaround uses just another bug in GCC :-)

Sergey Shandar wrote:
According to the standard, the code should not work.
14.8.2.2
- All references in the function type of the function template to the corresponding template parameters are replaced by the specified template argument values. If a substitution in a template parameter or in the function type of the function template results in an invalid type, type deduction fails. [Note: *The equivalent substitution in exception specifications is done only when the function is instantiated, at which point a program is ill-formed if the substitution results in an invalid type.*] Type deduction may fail for the following reasons:
However, it works on GCC. So, the workaround uses just another bug in GCC :-)
I too found that clause yesterday! http://tinyurl.com/22b4b7 Anyway your workaround is great. :-) Regards, -- Shunsuke Sogame

I took a quick look, looks pretty neat ;) I like it ;) Best, John
Hello all
I have my own C++ framework (http://cbear.berlios.de, SVN: http://tools.assembla.com/svn/cbear/trunk/) which has some useful (IMHO) libraries. One of this library is "cast" library (http://tools.assembla.com/cbear/browser/trunk/cbear.berlios.de/cast) which allows you to convert objects without specifying a type:
char c; int i; ... // if(c == static_cast<char>(i)) if(c == cast::static_::value(i)) { ... }
It is useful when you want to convert an object to a type of another object. And this is also more safe, compare to standard casting, for example in previous code someone can change the type of c to wchar_t, and if you use static_cast, the compiler will not even warn you about incorrect casting. So, you have to manually check all the code.
Currently there are several castings: static, reinterpret, const, dynamic, polymorphic (based on Boost.polymorphic_cast), polymorphic_down (based on Boost.polymorphic_downcast), explicit (calls an explicit constructor), safe_reinterpret (compare sizes of converting types), default (returns an object created by default constructor).
Thank you.
Best regards, Sergey Shandar. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- http://John.Torjo.com -- C++ expert ... call me only if you want things done right
participants (5)
-
Giovanni Piero Deretta
-
John Torjo
-
Sergey Shandar
-
shunsuke
-
Sid Sacek