Following small program does not give the expected result. It prints
some big negative value if compiled with my gcc 3.4.3 on linux or
intel-linux 8.1.
However commenting out either (one suffices) of the commented out lines
makes it work correctly. I don't understand what is happening here, can
anybody what is wrong with this function 'convert' or is the use of the
conversion library wrong?
<code>
#include
::convert( arg ) ; return temp ; }
int main() { int big = 900 ; ptrdiff_t diff = 16 ; std::cout << std::min( big, convert< int >( diff ) ) << std::endl ; return 0 ; } </code>
"Toon Knapen"
Following small program does not give the expected result. It prints some big negative value if compiled with my gcc 3.4.3 on linux or intel-linux 8.1.
However commenting out either (one suffices) of the commented out lines makes it work correctly. I don't understand what is happening here, can anybody what is wrong with this function 'convert' or is the use of the conversion library wrong?
<code> #include
#include <iostream> template
inline typename ::boost::numeric::converter ::result_type //convert ( const Source& arg ) // using this signatures makes it work convert ( Source arg ) { return ::boost::numeric::converter< Target, Source >::convert( arg ) ; } // { Target temp = ::boost::numeric::converter< Target, Source ::convert( arg ) ; return temp ; }
int main() { int big = 900 ; ptrdiff_t diff = 16 ; std::cout << std::min( big, convert< int >( diff ) ) << std::endl ;
return 0 ; } </code>
OK, this is a good one :-)
Whenever Source==Target, the library attempts to reduce the conversion to a
no-op;
That is, for the following code:
numeric::converter
Fernando Cacciola wrote: <snip>
int const& convert( int const& s ) { return s ; }
Notice that it takes a reference and returns a reference.
As such,
numeric::converter
::result_type is "int const&"; that is, a reference. and:
numeric::converter
::argument_type is also "int const&"
<snip>
A "fix" on your side would be to use ::boost::numeric::converter
::argument_type; but this isn't practical because users are forced to specify "Source" explicitely.
but in your example above you say that both 'result_type' and 'argument_type' result in a 'int const&' ? So replacing it would'nt make sens? I suppose 'argument_type' results in 'int', right ?
So you need "Source" to be the source type, but then, you also _need_ "Target" to be the result type:
template
inline Target convert2 ( Source arg ) { return ::boost::numeric::converter< Target, Source >::convert( arg ) ; } Incidentally, boost::numeric_cast<> (the new one) is equivalent to your code so is just as equally buggy.
I'm afraid I have to patch it not to use result_type anymore.
P.S: One could thing that the traits class, in the case of a trivial conversion, could define bare types instead of references (that is, making result_type being just "T" instead of "T const&). Altough this OK for builtin types, it isn't for the UDT, and it is precisly in the case of UDTs were the "reduction to a no-op in the trivial case" becomes really important. This means though that numeric_cast<> is better not used with UDTs in generic context when T==S is possible (because the optimization is then lost)
P.S.2: Of course the alternative is to use "Source const&" instead of "Source"... I don't really remember the details but I seem to recall that the original numeric_cast<> used a non-reference argument for some good reason; and so I just kept that.
Thanks for the report!
Fernando Cacciola SciSoft
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Check out our training program on acoustics and register on-line at http://www.fft.be/?id=35
"Toon Knapen"
Fernando Cacciola wrote:
<snip>
A "fix" on your side would be to use ::boost::numeric::converter
::argument_type; but this isn't practical because users are forced to specify "Source" explicitely. but in your example above you say that both 'result_type' and 'argument_type' result in a 'int const&' ? So replacing it would'nt make sens? I suppose 'argument_type' results in 'int', right ?
No, argument_type is "int const&". I meant to use these in your wrapper. There you mix result_type with Source. Fernando Cacciola SciSoft
Fernando Cacciola wrote:
Whenever Source==Target, the library attempts to reduce the conversion to a no-op;
Thinking about this I was wondering if it isn't dangerous that the semantics change from one specialisation to another of the same template?! Would'nt it be better to have the same semantics for all cases and just rely on the optimiser. toon
participants (2)
-
Fernando Cacciola
-
Toon Knapen