Re: C++ and packed decimal strange behavior
Qian Ren <[email protected]>
| Newsgroups | gmane.comp.lang.as400.c |
|---|---|
| Message-ID | <OF83A473BB.63E6DBDE-ON48257E8A.0037C864-48257E8A.00391795@cn.ibm.com> |
Hi Jevgeni,
Your understanding is correct. When E1 and E2 can be converted to the type
of the other, compiler has no way to decide which conversion should be
followed.
And some comments on your experiment 1 and 3 .
For the 1st one, the explicit type conversion makes E1 and E2 have the same
type.
For the 3rd one, v1 = (memcmp(Day1, Day2, 7) <= 0) ?
v2 - v3 - v4 : --> E1
v2 - v4 - (_ConvertDecimal)("0"); --> E2
E1 has type "_DecimalT<17,0>". E2 has type "_ConvertDecimal" becasue we
have following operator overloading for '-':
template<int dig1, int prec1>
inline _ConvertDecimal
operator - (const _DecimalT<dig1,prec1> & val1, const _ConvertDecimal &
val2);
Because bcd.h header file declares the following constructor and conversion
function in class _DecimalT, E1 can be converted to E2 (by conversion
function) and E2 can be convert to E1 (by constructor). As a result,
compiler can not decide which conversion should be followed.
template<int dig, int prec>
class _DecimalT
{
public:
...
inline _DecimalT (const _ConvertDecimal val);
...
inline operator _ConvertDecimal ();
...
};
Thank you.
Qian Ren (Jarod)
Hi Jarod,
First of all thanks for clarification. I expected that what works in C will
also work in C++ - invalid assumption at least with packed decimals...
Did I understood correctly that the problem is based on the fact that
compiler has no ways to decide either to convert decimal(17.0) to
decimal(16,0) or vice versa?
Assuming that I made 3 experiments: two with positive results, one with
negative.
This works:
v1 = (memcmp(Day1, Day2, 7) <= 0) ?
(decimal (15,0)) (v2 - v3 - v4) :
(decimal (15,0)) (v2 - v4 ) ;
probably because both E1 and E2 are cast to decimal (15,0) explicitly.
This works:
...
decimal (15,0) v5 ;
v5 = __D("0") ;
v1 = (memcmp(Day1, Day2, 7) <= 0) ?
v2 - v3 - v4 :
v2 - v4 - v5 ;
because both E1 and E2 are already decimal (17,0).
And this does not work:
#define __D("0") ;
v1 = (memcmp(Day1, Day2, 7) <= 0) ?
v2 - v3 - v4 :
v2 - v4 - ZERO ;
with an error message
CZP0207 No common type found for operands with type "_DecimalT<17,0>" and
"_ConvertDecimal".
Thanks again,
Jevgeni.
On Tue, Jul 21, 2015 at 8:38 PM, Qian Ren <[email protected]> wrote:
> 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.
>
>
--
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.
--
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.