Working with Large Values (double)

J

jacob navia

Le 24/02/2014 14:58, Stefan Ram a écrit :
Because in C++, the user can always use the same verb:

... << x ...
... << i ...

while in C, he has to remember individual verbs per type

print_double( x )
print_int( x )

With a consistent naming convention I do not see how this could ever be
a problem.

print_xxx(XXX *data);

is quite easy to use, remember, etc, the same as <<.
or cannot infer a static type at all, because the type is
not know at compile time, in which case one needs to start
to implement OO in C, which is already supplied by the
language in C++.

As far as I remember C++ is statically typed language, i.e. everything
is known at compile time. Objective C, is not, and you use the method
lookup of the language to figure out dynamically what "print" function
would be called. There is no method lookup in c++ so the compiler
generates in the case of a virtual function a lookup in a specific class
hierarchy that must be given to it at compile time. True, there is a
genericity here that is not there in C.

Do I need that?

How much does that costs me in memory area in my cramped brain?

Do I want that?

Those are questions that everyone answers as he/she likes/must.
I would not blame anyone for choosing C++, I have even worked debugging
C++, everyone must try to feed his/her family somehow.

What bothers me precisely is this lack of respect from C++ programmers
that believe that because they have mastered some c++ trivialities they
are better than people that do not care about them.

Look at how java programmers are laughed at here. Or Fortran
programmers, or whatever. It is this attitude, this lack of respect that
I question.

Thanks
 
V

Victor Bazarov

Le 24/02/2014 12:32, Juha Nieminen a écrit :

In C++ you have to overload the operator << as far as I remember. In C
you have to write a "Print_XXX" function. I do not see why C++ is so
fundamentally better.

Too bad. Perhaps you can read more about overloading, it's one
important feature of C++ that sets it aside from C.
But I am afraid you will never be convinced (of course). [..]

You took the words right out of my mouth (fingertips)... :)

V
 
W

Wouter van Ooijen

jacob navia schreef op 24-Feb-14 3:14 PM:
There is no method lookup in c++ so the compiler
generates in the case of a virtual function a lookup in a specific class
hierarchy that must be given to it at compile time. True, there is a
genericity here that is not there in C.

For the simple case of <<'ing a value no virtual function lookup is
needed, because the compiler knows the type of the rhs and hence which
method or function to call. A vft is needed only when the rhs is
(derived from) a base type that has a virtual << method.

Wouter van Ooijen
 
J

jacob navia

Le 24/02/2014 15:14, Victor Bazarov a écrit :
Perhaps you can read more about overloading, it's one important feature
of C++ that sets it aside from C.

I have implemented function overloading in my compiler system lcc-win.
And true, I have read a lot of things about overloading, and also about
how overloading (like anything) can be ABUSED.

For example, the expression

String a,b,c;
c = a+b;

is an *abuse* of overloading.

Why?

Because there is no ADDITION being done when a and b are STRINGS but a
concatenation of two strings, what is *completely different*. If a and b
are strings we have

a+b != b+a

what goes against all the mathematical basis of addition as normal
people use that word.

That is why string "addition" is an ABUSE of overloading.

In the same vein, shifting left an object to print it just because the
opeartor << looks like the head of a left arrow or suggests "put into"
is NONSENSE and an abuse of the overloading concept.

This WRONG DESIGN DECISION is at the heart of a catastrophe in c++ i/o
as I showed in my example.

No, output has nothing to do (really *NOTHING*) with left shift, and the
whole concept precludes querying the state of the output machine,
precludes a simpler syntax, etc. This is so true that now there are C++
packages that output their data without operator overloading.

As I documented in the documentation of my compiler system, overloading
works best when used with NUMBERS or NUMERIC data. It is also a great
idea when used with arrays (overloading operator []). But in OTHER
applications it can be an incredibly BAD idea.

The world is a complex place and there is no magic bullets Mr Bazarov.
Things that are good in some contexts are BAD in another. Knives are
great for cutting bread, but they can cut your finger as easily too.

Beware!

:)

jacob

P.S. It would be great if you wouldn't assume that other people that do
not agree with c++'s decisions are ignorants that "should read more".
Thanks.
 
J

jacob navia

Le 24/02/2014 15:21, Wouter van Ooijen a écrit :
jacob navia schreef op 24-Feb-14 3:14 PM:


For the simple case of <<'ing a value no virtual function lookup is
needed, because the compiler knows the type of the rhs and hence which
method or function to call. A vft is needed only when the rhs is
(derived from) a base type that has a virtual << method.

Wouter van Ooijen

I know, I was speaking of the general case of course. In the << case the
compiler saves the programmer the effort of remembering the name of the
output function since all syntax is just <<.
As I said before, using a simple

print_xxx

naming convention makes this as easy to remember as the << syntax.

Besides, if you want to support SEVERAL print functions for instance for
formatting a customer with name, age or name, SS number, or just
initials, etc you will need anyway several print functions in C++ also,
if I remember correctly isn't it?

jacob
 
V

Victor Bazarov

Le 24/02/2014 15:14, Victor Bazarov a écrit :
Perhaps you can read more about overloading, it's one important feature
of C++ that sets it aside from C.

I have implemented function overloading in my compiler system lcc-win.
And true, I have read a lot of things about overloading, and also about
how overloading (like anything) can be ABUSED.

For example, the expression

String a,b,c;
c = a+b;

is an *abuse* of overloading.
[.. rant about operator overloading removed ..]

You really need to stop taking everything as an attack, you know. When
I mentioned overloading, I did really mean *function* overloading. And,
curiously enough, as you do claim to have "implemented function
overloading", you immediately go on giving an example of *operator*
overloading as a feature that is prone to abuse...

Well, let me be a bit more verbose, as now I see that my *assumption* of
your somewhat skewed knowledge of overloading was most likely the cause
for your "disagreement".

When you define 'print' function for other types, the main advantage the
overloading gives you is that you don't need to name those functions
differently.

... print(const OneType& val);

can easily coexist in C++ with

... print(const SomeOtherType& val);

which gives you this important feature -- you can write in your code

print(someObject);

without having to remember what type 'someObject' has. The compiler
will pick the right function for you.
P.S. It would be great if you wouldn't assume that other people that do
not agree with c++'s decisions are ignorants that "should read more".

Even if you are not "an ignorant", the pattern of your disagreement
"with c++'s decisions" does indeed suggest that you should read more,
and I am not sorry that I assumed as much.

V
 
W

Wouter van Ooijen

jacob navia schreef op 24-Feb-14 3:34 PM:
Besides, if you want to support SEVERAL print functions for instance for
formatting a customer with name, age or name, SS number, or just
initials, etc you will need anyway several print functions in C++ also,
if I remember correctly isn't it?

In true C++: if that is what you want it is cetainly possible, just like
you can have print_xxx functions if you want to.

I think I would prefer to reserve operator<<(person) for (debug)
printing of ALL data in person, and have separate getters for the items
that you might want to print, like

std::cout
<< std::setw( 30 ) << person.name()
<< " lives at "
<< std::setw( 60 ) << person.adress();

This keeps *what* you want to print separate from *how* you want to
print it.

Wouter van Ooijen
 
W

Wouter van Ooijen

jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
String a,b,c;
c = a+b;

is an *abuse* of overloading.

Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?

// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Python, with compile-time support for checking the format string
msg = "M [name[%s],address[%s] END" % ( x.name, x.address )

// No tricks, using nested concatenate function (LISP style??)
msg = concatenate(
"M name["
concatenate(
x.name
concatenate(
"],address["
concatenate(
x.address,
"] END")))));

// sequence of append calls (C style??)
msg = ""
append( msg, "M name[" );
append( msg, x.name );
append( msg, "],address[" );
append( msg, x.address );
append( msg, "] END" );
 
J

jacob navia

Le 24/02/2014 15:54, Victor Bazarov a écrit :
When I mentioned overloading, I did really mean *function* overloading.

Well, strange, since we were talking about the << syntax of c++ for
OUTPUT, what is operator overloading and NOT function overloading.

It is a pity that all my arguments are brushed aside as "a rant" and you
do not even go into them.

This is convenient for you of course, since the sorry state of affairs
in c++ because precisely too much operator overloading when formatting
is at the center of this dicussion.

Now, to come back to a function overload solution:

Having a SINGLE print function to print ANY object looks great at first
but then... how do you remember which one to use?


Suppose

void print(XXX *data1);
void print(XXX *data1, FILE *sink);
void print(XXX *data1, int printFlags, FILE *sink);
void print(XXX *data1, int printFlags, int linewidth); // Uses stdout
void print(YYY *data2, long long printflags);
void print(YYY *data2, CUSTOMER *c, long long flags);

etc.

Now the programmer must remember which arguments/argument order is
necessary for each function... And since all have the SAME name
remembering them is MUCH more difficult than

void print_noargs(XXX *data1);
void printWithSink(XXX *data1, FILE *sink);
void printFlagsSink(XXX *data1, int flags, FILE *sink);

or other similar simple naming schema.

You see?

IT DEPENDS!

If you have few "print" functions with identical number of arguments
overloading is OK, but as the print functions proliferate, it becomes
more and more difficult to use the correct one!

*IT DEPENDS*

That is what many C++ heads do not understand. The world is very complex
and single solutions are good in some contexts, bad in another,
the same as I said from operator overloading.

Thanks for your input.
 
W

Wouter van Ooijen

Scott Lurndal schreef op 24-Feb-14 3:56 PM:
Modern compilers are good at warning about varargs argument mismatches
with the format string.

That might be the case, but it is a mechanism that is closed to the
programmer (or library developer).
Modern C++ has become almost unreadable.

Y ain't seen nothing yet! Try template metaprogramming :)

Wouter van Ooijen
 
S

Stefan Ram

Wouter van Ooijen said:
Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?
// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Perl, overloading .
msg = "M name[" . name . "],address[" . address . "] END";

// VBA, overloading &
msg = "M name[" & name & "],address[" & address & "] END"

This solves the objection of overloading »+« against its
supposed semantics of the mathematical addition, while it
keeps the other advantages of a notation with a binary
operator for concatenation.

Yet, I have never observed any real problems with
overloading »+« to mean string concatenation.
 
J

jacob navia

Le 24/02/2014 16:14, Wouter van Ooijen a écrit :
jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
String a,b,c;
c = a+b;

is an *abuse* of overloading.

Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?

// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Python, with compile-time support for checking the format string
msg = "M [name[%s],address[%s] END" % ( x.name, x.address )

// No tricks, using nested concatenate function (LISP style??)
msg = concatenate(
"M name["
concatenate(
x.name
concatenate(
"],address["
concatenate(
x.address,
"] END")))));

// sequence of append calls (C style??)
msg = ""
append( msg, "M name[" );
append( msg, x.name );
append( msg, "],address[" );
append( msg, x.address );
append( msg, "] END" );

Please, this is beginner level question


Solution 1: (preferred)
-----------------------
int strcatMany(char *first,...);

calling sequence:

strcatMany(a,b,c,NULL);

or another:

Solution 2
----------
strcatMany(int n,...);

calling sequence:

strcatMany(4,"1","2,"3","4");
This is not so good because you can make a mistake counting the strings.

jacob
 
J

jacob navia

Le 24/02/2014 16:26, Stefan Ram a écrit :
Wouter van Ooijen said:
Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?
// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Perl, overloading .
msg = "M name[" . name . "],address[" . address . "] END";

// VBA, overloading &
msg = "M name[" & name & "],address[" & address & "] END"

This solves the objection of overloading »+« against its
supposed semantics of the mathematical addition, while it
keeps the other advantages of a notation with a binary
operator for concatenation.

Yet, I have never observed any real problems with
overloading »+« to mean string concatenation.

What about the problem of the intermediate results?

When using

zz=a+b+c+d;

the compiler must realize that it is better to avoid intermediate
results! This makes the compiler specialize in a special case of
operator overloading. Is this justified?

And another problem

zz = a + b + 12;

b+12 is defined in C (and C++) since it is a pointer+integer addition
giving a pointer to 12 characters after the start of b.

What happens there? Will the compiler silently accept that mistake?

You see?

The INTERACTIONS between features are also a problem.
 
W

Wouter van Ooijen

jacob navia schreef op 24-Feb-14 4:28 PM:
Solution 1: (preferred)
-----------------------
int strcatMany(char *first,...);

calling sequence:

strcatMany(a,b,c,NULL);

strcatMany( a, b, c );

:(

Wouter van Ooijen

PS Jacob, why are you hanging out of a C++ forum?
 
V

Victor Bazarov

Le 24/02/2014 15:54, Victor Bazarov a écrit :

Well, strange, since we were talking about the << syntax of c++ for
OUTPUT, what is operator overloading and NOT function overloading.

If you care to reread the thread, I decided to reply to you when you stated

Le 24/02/2014 12:32, Juha Nieminen a écrit :

In C++ you have to overload the operator << as far as I remember. In C
you have to write a "Print_XXX" function. I do not see why C++ is so
fundamentally better.

So, let me repeat.

C++ is so "fundamentally better" that you don't have to write Print_XXX
function with different XXX for every different type.

Moreover, making 'print_whatnot' a stand-alone function would probably
be a design mistake in that case anyway. Most likely it's better to
split the responsibilities between three parts of the design -- the
class that needs to be printed, the sink that handles the actual output
and the template that binds the two.

But again, this discussion is not about how to design an output for a
combination of object types and sinks, is it?
It is a pity that all my arguments are brushed aside as "a rant" and you
do not even go into them.

There is no depth in them that would allow anybody to "go into them",
unfortunately.
This is convenient for you of course, since the sorry state of affairs
in c++ because precisely too much operator overloading when formatting
is at the center of this dicussion.

Now, to come back to a function overload solution:

Having a SINGLE print function to print ANY object looks great at first
but then... how do you remember which one to use?

"Are you saying that I can dodge bullets?"
"I am saying that when you are ready, you won't have to."

(or something like that). You're still thinking in C terms. You don't
have to remember which function to use *when* your output subsystem is
designed and implemented properly, using not C but C++ mechanisms as
they are intended to be used.
Suppose

void print(XXX *data1);
void print(XXX *data1, FILE *sink);
void print(XXX *data1, int printFlags, FILE *sink);
void print(XXX *data1, int printFlags, int linewidth); // Uses stdout
void print(YYY *data2, long long printflags);
void print(YYY *data2, CUSTOMER *c, long long flags);

etc.

Now the programmer must remember which arguments/argument order is
necessary for each function... And since all have the SAME name
remembering them is MUCH more difficult than

void print_noargs(XXX *data1);
void printWithSink(XXX *data1, FILE *sink);
void printFlagsSink(XXX *data1, int flags, FILE *sink);

or other similar simple naming schema.

You see?

No, I don't see. What I see is a C approach to designing C++
interfaces, and *that* is the most common problem leading to the
dismissal of C++ features by those who come from long (too long if you
ask me) time use of C.

It's not impossible for C programmers to adopt the correct approach and
learn C++ ways -- I've seen it happen, but more often than not it's due
to what seems their lack of interest or fear to have to apply effort or
to leave the comfort of well-learned C idioms that they stay in their
playpen and keep trying to use their trusted building blocks instead of
getting to know a complex erector set.
IT DEPENDS!

If you have few "print" functions with identical number of arguments
overloading is OK, but as the print functions proliferate, it becomes
more and more difficult to use the correct one!

*IT DEPENDS*

That is what many C++ heads do not understand. The world is very complex
and single solutions are good in some contexts, bad in another,
the same as I said from operator overloading.

Thanks for your input.

You're welcome.

It looks that you're just starting on the journey that is C++. You have
made a few wrong steps and your feet start to ache or perhaps you
twisted your ankle because you weren't watchful enough for rocks just
underneath the surface. Two thoughts come to mind. Don't let a small
pain divert you from the right path. And, when in shallows, don't
pretend you're treading water -- others who have already passed that
part of the way will see right through that.

Good luck in your studies!

V
 
S

Stefan Ram

jacob navia said:
zz=a+b+c+d;
the compiler must realize that it is better to avoid intermediate
results! This makes the compiler specialize in a special case of
operator overloading. Is this justified?

Why not?

C++ compilers also can optimize away some intermediate
results by means of the general application of move
semantics and of as-if semantics.

In Java, "abc"+"def" is compiled to "abcdef".
In C++, "abc"+"def" is not concatenation in spite of a C++ book
that claimed so.

When one wants to optimize, one can always do so:

#include <iostream>
#include <ostream>
#include <string>

int main()
{ ::std::string s{ "abc" };
s.reserve( 16);
s += "def";
s += "ghi";
s += "jkl";
::std::cout << s << '\n'; }
And another problem
zz = a + b + 12;
b+12 is defined in C (and C++) since it is a pointer+integer addition
giving a pointer to 12 characters after the start of b.

By left associativity of »+«, »b + 12« is not a
subexpression of »a + b + 12«.
 
V

Victor Bazarov

Le 24/02/2014 16:26, Stefan Ram a écrit :
Wouter van Ooijen said:
Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?
// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Perl, overloading .
msg = "M name[" . name . "],address[" . address . "] END";

// VBA, overloading &
msg = "M name[" & name & "],address[" & address & "] END"

This solves the objection of overloading »+« against its
supposed semantics of the mathematical addition, while it
keeps the other advantages of a notation with a binary
operator for concatenation.

Yet, I have never observed any real problems with
overloading »+« to mean string concatenation.

What about the problem of the intermediate results?

When using

zz=a+b+c+d;

the compiler must realize that it is better to avoid intermediate
results! This makes the compiler specialize in a special case of
operator overloading. Is this justified?

You make it sound that the existence of move c-tors is somehow
unjustified in C++. Using proper technique helps the compiler to avoid
having to "realize that it is better". The compiler is but a tool, and
it is *you* who realize (or not, like in this case) *what* is *better*
and what isn't.
And another problem

zz = a + b + 12;

b+12 is defined in C (and C++) since it is a pointer+integer addition
giving a pointer to 12 characters after the start of b.

What happens there? Will the compiler silently accept that mistake?

No. You can't overload operators for built-in types. If 'b' is a
pointer, b + 12 is a pointer. If 'b' is a string type with an
overloaded '+' operator, it will either have an overloaded variation
that accepts 'int' as its argument, or the compiler will report an error.

All I see is ignorance so far.
The INTERACTIONS between features are also a problem.

Perhaps you care to post a complete C++ program that illustrates that.

V
 
V

Victor Bazarov

Le 24/02/2014 16:14, Wouter van Ooijen a écrit :
jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
String a,b,c;
c = a+b;

is an *abuse* of overloading.

Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?

// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Python, with compile-time support for checking the format string
msg = "M [name[%s],address[%s] END" % ( x.name, x.address )

// No tricks, using nested concatenate function (LISP style??)
msg = concatenate(
"M name["
concatenate(
x.name
concatenate(
"],address["
concatenate(
x.address,
"] END")))));

// sequence of append calls (C style??)
msg = ""
append( msg, "M name[" );
append( msg, x.name );
append( msg, "],address[" );
append( msg, x.address );
append( msg, "] END" );

Please, this is beginner level question


Solution 1: (preferred)
-----------------------
int strcatMany(char *first,...);

calling sequence:

strcatMany(a,b,c,NULL);

or another:

Solution 2
----------
strcatMany(int n,...);

calling sequence:

strcatMany(4,"1","2,"3","4");
This is not so good because you can make a mistake counting the strings.

You can make a mistake of providing a wrong variable in that list and
the compiler is unfortunately *impotent* to help you:

int fortytwo = 42;
char* two = "2";
char* here = "1";
...
strcatMany(here, two, fortytwo, NULL);

(not to mention that 'here' probably has not enough room to contain the
entire string, and you *need to remember that*). There is so much that
is wrong with those approaches.

V
 
M

Martin Shobe

Le 24/02/2014 16:26, Stefan Ram a écrit :
Wouter van Ooijen said:
Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?
// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Perl, overloading .
msg = "M name[" . name . "],address[" . address . "] END";

// VBA, overloading &
msg = "M name[" & name & "],address[" & address & "] END"

This solves the objection of overloading »+« against its
supposed semantics of the mathematical addition, while it
keeps the other advantages of a notation with a binary
operator for concatenation.

Yet, I have never observed any real problems with
overloading »+« to mean string concatenation.

What about the problem of the intermediate results?

When using

zz=a+b+c+d;

the compiler must realize that it is better to avoid intermediate
results! This makes the compiler specialize in a special case of
operator overloading. Is this justified?

Why must it realize that? It's certainly allowed to, but "must"?
And another problem

zz = a + b + 12;

b+12 is defined in C (and C++) since it is a pointer+integer addition
giving a pointer to 12 characters after the start of b.

What happens there? Will the compiler silently accept that mistake?

The precedence rules say that 12 is added to the results of a + b. So
that particular mistake doesn't occur. Since you appear to be
overloading "+" for "char *", zz would now contain the address of a[12],
while a would contain the concatenation of a + b.

Unintuitive, certainly. It's why I wouldn't overload + on "char *". For
a string class, this wouldn't be an issue.

Martin Shobe
 
M

Martin Shobe

Le 24/02/2014 16:14, Wouter van Ooijen a écrit :
jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
String a,b,c;
c = a+b;

is an *abuse* of overloading.

Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?

// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Python, with compile-time support for checking the format string
msg = "M [name[%s],address[%s] END" % ( x.name, x.address )

// No tricks, using nested concatenate function (LISP style??)
msg = concatenate(
"M name["
concatenate(
x.name
concatenate(
"],address["
concatenate(
x.address,
"] END")))));

// sequence of append calls (C style??)
msg = ""
append( msg, "M name[" );
append( msg, x.name );
append( msg, "],address[" );
append( msg, x.address );
append( msg, "] END" );

Please, this is beginner level question


Solution 1: (preferred)
-----------------------
int strcatMany(char *first,...);

calling sequence:

strcatMany(a,b,c,NULL);

or another:

Solution 2
----------
strcatMany(int n,...);

calling sequence:

strcatMany(4,"1","2,"3","4");
This is not so good because you can make a mistake counting the strings.

jacob

Aside from using names that have been reserved, this is silently
undefined behavior if we try the following (a situation you used to
denigrate overloading +):

strcatMany(a, b, 12);

Even that aside, the only way you've left to get the concatenated string
is through a global variable. I find that to be a serious deficiency,
though one that can be fixed.

int Concatenate(char * dest, char const * first, ...);
int ConcatenateN(char * dest, int n, ...);

Martin Shobe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top