Re: C++ and packed decimal strange behavior

Qian Ren <[email protected]>
Newsgroups gmane.comp.lang.as400.c
Message-ID <[email protected]>
Jevgeni Astanovski <jevgeniast@...> writes:

> 
> Hi, all.
> I'm really new with C++ and recently while porting a program from ILE/C to
> ILE/C++ ran into a strange effect that I cannot explain. Maybe someone can
> help me.
> 
> Here's a simple program:
> 
> #include <stdlib.h>
> #include <bcd.h>
> 
> int main (int argc, char *argv[])
> {
>   char Day1[7], Day2[7] ;
>   _DecimalT<15, 0> v1, v2, v3, v4 ;
> 
>   memset (Day1, '0', 7) ;
>   memset (Day2, '1', 7) ;
> 
>   v2 = __D("100") ;
>   v3 = __D("10") ;
>   v4 = __D("200") ;
> 
>   v1 = (memcmp(Day1, Day2, 7) <= 0) ? v2 - v3 - v4 : v2 - v4 ;
> 
>   return(0) ;
> }
> 
> Attempt to compile it produces error message for conditional assignment:
> CZP0207 No common type found for operands with type "_DecimalT<17,0>" and
> "_DecimalT<16,0>".
> 
> However when I change it (put a plain conditional statement):
> 
> #include <stdlib.h>
> #include <bcd.h>
> 
> int main (int argc, char *argv[])
> {
>   char Day1[7], Day2[7] ;
>   _DecimalT<15, 0> v1, v2, v3, v4 ;
> 
>   memset (Day1, '0', 7) ;
>   memset (Day2, '1', 7) ;
> 
>   v2 = __D("100") ;
>   v3 = __D("10") ;
>   v4 = __D("200") ;
> 
>   if (memcmp(Day1, Day2, 7) <= 0)
>     v1 = v2 - v3 - v4 ;
>   else
>     v1 = v2 - v4 ;
> 
>   return(0) ;
> }
> 
> Program compiles fine without errors...
> 
> In ILE/C both compile, of course....
> 
> What is the difference?
> 
> TIA,
> 
> Jevgeni.


Hi Jevgeni,

According to the C++ standard (section 5.16 Conditional operator), the
expression "(memcmp(Day1, Day2, 7) <= 0) ? v2 - v3 - v4 : v2 - v4" is
ill-formed.

For a conditional expression "condition? E1 : E2", if the E1 and E2 have
different types, an attempt is made to convert each of them to the type of
the other(5.16.3).  The type of expression "v2-v3-v4" is _DecimalT<17, 0>. 
And the type of expression "v2-v4" is _DecimalT<16, 0>.  So compiler will
try to convert the type of "v2-v3-v4" to _DecimalT<16, 0> and try to convert
the type of "v2-v4" to _DecimalT<17, 0>.

The bcd.h header file defines the following constructor of template class
_DecimalT.  So each of "v2-v3-v4" and "v2-v4" can be converted to the type
of other.  And according to the standard, if both E1 and E2 can be
converted, or one can be converted but the conversion is ambiguous, the
program is ill-formed (5.16.3).

    template<int dig, int prec>
    template<int dig2, int prec2>
    inline _DecimalT<dig,prec>::_DecimalT (const _DecimalT<dig2, prec2> val) {
    ......
    }

I think another possible work around is to change the statement to
"(memcmp(Day1, Day2, 7) <= 0) ? v1 = v2 - v3 - v4 : v1 = v2 - v4;".

Here is the link of the C++ stardand draft
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf).  You
could read section 5.16 for details.

Thank you.

Qian Ren (Jarod)

-- 
This is the Bare Metal Programming IBM i (AS/400 and iSeries) (C400-L) mailing list
To post a message email: C400-L-Zwy7GipZuJhWk0Htik3J/[email protected]
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request-Zwy7GipZuJhWk0Htik3J/[email protected]
Before posting, please take a moment to review the archives
at http://archive.midrange.com/c400-l.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.