Implicit cast rules

Hey everyone, Would someone please explain to me the implicit cast rule that prevents the following from compiling, and/or if there is a way around it? #include <boost/optional.hpp> #include <iostream> using namespace boost; using namespace std; struct C { operator optional<int>() { return none; } }; int main() { C c; cout << static_cast<optional<int> >(c) << endl; return 0; } Error message: In file included from /usr/include/boost/optional.hpp:15, from cast-to-optional.cpp:1: /usr/include/boost/optional/optional.hpp: In member function ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = C, T = int]’: /usr/include/boost/optional/optional.hpp:262: instantiated from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = C, T = int]’ /usr/include/boost/optional/optional.hpp:559: instantiated from ‘boost::optional<T>::optional(const Expr&) [with Expr = C, T = int]’ cast-to-optional.cpp:13: instantiated from here /usr/include/boost/optional/optional.hpp:392: error: cannot convert ‘const C’ to ‘int’ in initialization I can tell what is happening; it would seem that the implicit cast rule selects the optional() constructor before it even looks at my more specific cast operator. I'm just confused about why this should be, since I see no reason why constructor casts should be prioritized over operator casts. Is this just the way it is, a GCC quirk, something I'm doing wrong, etc? Thanks! Greg

2011/5/24 Gregory Crosswhite <gcross@phys.washington.edu>
Hey everyone,
Hi Greg
Would someone please explain to me the implicit cast rule that prevents the following from compiling, and/or if there is a way around it?
#include <boost/optional.hpp> #include <iostream>
using namespace boost; using namespace std;
struct C { operator optional<int>() { return none; } };
int main() { C c; cout << static_cast<optional<int> >(c) << endl; return 0; }
Error message:
In file included from /usr/include/boost/optional.hpp:15, from cast-to-optional.cpp:1: /usr/include/boost/optional/optional.hpp: In member function ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = C, T = int]’: /usr/include/boost/optional/optional.hpp:262: instantiated from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = C, T = int]’ /usr/include/boost/optional/optional.hpp:559: instantiated from ‘boost::optional<T>::optional(const Expr&) [with Expr = C, T = int]’ cast-to-optional.cpp:13: instantiated from here /usr/include/boost/optional/optional.hpp:392: error: cannot convert ‘const C’ to ‘int’ in initialization
I can tell what is happening; it would seem that the implicit cast rule selects the optional() constructor before it even looks at my more specific cast operator. I'm just confused about why this should be, since I see no reason why constructor casts should be prioritized over operator casts. Is this just the way it is, a GCC quirk, something I'm doing wrong, etc?
The compiler sais "cannot convert 'const C' to 'int'. I think it means static_cast<> takes c as a const, and your conversion operator is not a const member, so the compiler cannot use it. Solution (not tested): operator optional<int>() const { return none; } Regards Kris

On Tue, May 24, 2011 at 1:41 PM, Krzysztof Czainski <1czajnik@gmail.com>wrote:
The compiler sais "cannot convert 'const C' to 'int'. I think it means static_cast<> takes c as a const, and your conversion operator is not a const member, so the compiler cannot use it. Solution (not tested):
operator optional<int>() const { return none; }
That doesn't work either, nor does cout << ( optional<int> ) c << endl; but this does cout << c.operator optional<int>( ) << endl; But I guess that's not really what you're looking for. HTH - Rob.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday, May 24, 2011, Gregory Crosswhite wrote:
Hey everyone,
Would someone please explain to me the implicit cast rule that prevents the following from compiling, and/or if there is a way around it?
It's standard behavior of static_cast 5.2.9 paragraph 2. If you did the conversion implicitly instead of explicitly with static_cast, then the boost::optional constructor that is causing you trouble would not be considered (since it is explicit).
I can tell what is happening; it would seem that the implicit cast rule selects the optional() constructor before it even looks at my more specific cast operator. I'm just confused about why this should be, since I see no reason why constructor casts should be prioritized over operator casts. Is this just the way it is, a GCC quirk, something I'm doing wrong, etc?
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iEYEARECAAYFAk3bwiUACgkQ5vihyNWuA4Vw7QCgt+b7prO/646nZ5gaD8tQ4t9S i2YAoIrtOzh3SkJwWCMxIUIc1s2a6HOh =2mdf -----END PGP SIGNATURE-----

Gregory Crosswhite wrote:
Hey everyone,
Would someone please explain to me the implicit cast rule that prevents the following from compiling, and/or if there is a way around it?
#include <boost/optional.hpp> #include <iostream>
using namespace boost; using namespace std;
struct C { operator optional<int>() { return none; } };
int main() { C c; cout << static_cast<optional<int> >(c) << endl; return 0; }
Error message:
In file included from /usr/include/boost/optional.hpp:15, from cast-to-optional.cpp:1: /usr/include/boost/optional/optional.hpp: In member function ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = C, T = int]’: /usr/include/boost/optional/optional.hpp:262: instantiated from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = C, T = int]’ /usr/include/boost/optional/optional.hpp:559: instantiated from ‘boost::optional<T>::optional(const Expr&) [with Expr = C, T = int]’ cast-to-optional.cpp:13: instantiated from here /usr/include/boost/optional/optional.hpp:392: error: cannot convert ‘const C’ to ‘int’ in initialization
I can tell what is happening; it would seem that the implicit cast rule selects the optional() constructor before it even looks at my more specific cast operator. I'm just confused about why this should be, since I see no reason why constructor casts should be prioritized over operator casts. Is this just the way it is, a GCC quirk, something I'm doing wrong, etc?
Hi, from N3242 5.2.9 "4 Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue." I don't know why the standard uses a temporary variable T t(e) and return it instead of returning directly T(e). HTH, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Implicit-cast-rules-tp3546218p3547294.htm... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (5)
-
Frank Mori Hess
-
Gregory Crosswhite
-
Krzysztof Czainski
-
Robert Jones
-
Vicente Botet