Sunday, January 3, 2021

Digest for comp.lang.c++@googlegroups.com - 24 updates in 6 topics

"Öö Tiib" <ootiib@hot.ee>: Jan 03 08:36AM -0800


> > Why to reinvent a wheel?
> I'm sure you already know this, but for open source libraries, users for
> the most part do not want dependencies on other libraries.
 
I myself am usually annoyed by wheels reinvented (square as rule)
instead of using standard library, or whatever other library be it
boost, eigen, sdl, rapidjson, ncurses and long list of others I know
that work.
 
> > Quite decent implementation is available
> But not self-contained in one or two files.
 
So what? What are you requiring from what you got for free? Do it
yourself. You can extract it and make compile-time option to use your
extracted version as third alternative to std::basic_string_view and
boost::basic_string_view. Does anyone want your reinvented thing?
Who?
 
The resulting naive garbage is what I've learned to frown at. Anecdotal
history of binary search is most clear example of what I observe from
day to day:
 
"When Jon Bentley assigned binary search as a problem in a
course for professional programmers, he found that ninety
percent failed to provide a correct solution after several hours
of working on it, mainly because the incorrect implementations
failed to run or returned a wrong answer in rare edge cases. A
study published in 1988 shows that accurate code for it is only
found in five out of twenty textbooks."
<https://en.wikipedia.org/wiki/Binary_search_algorithm>
 
It all is same about professional programmers of 2021, about
binary search and about lot of other similarly "trivial" things they
reinvent. If I see it then they fail my review with
"Use std::lower_bound here!".
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jan 03 06:11PM

On Sun, 2021-01-03, Öö Tiib wrote:
...
> study published in 1988 shows that accurate code for it is only
> found in five out of twenty textbooks."
> <https://en.wikipedia.org/wiki/Binary_search_algorithm>
 
That's weird. I remember the class circa 1991 when we tried to
implement binary search, and I remember who came up with the right
solution (not me). We all knew (or learned) it was hard and, more
importantly, we knew how to prove an implementation was correct (with
invariants and such).
 
Perhaps our education was better than average, but why bother teaching
binary search if you don't do it properly?
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Öö Tiib" <ootiib@hot.ee>: Jan 03 12:28PM -0800

On Sunday, 3 January 2021 at 20:11:56 UTC+2, Jorgen Grahn wrote:
> invariants and such).
 
> Perhaps our education was better than average, but why bother teaching
> binary search if you don't do it properly?
 
All people learn. Even the teachers learn. Study published 1988 made
it lot better by 1991. But people forget and old teachers retire. IT has
high salaries so only weak specialists become teachers and at 2021
you can easily find that majority of professional programmers fail
miserably when attempting to implement binary search.
 
Same with reinventing whatever other thing. Did you see "But [the freely
available implementation is] not self-contained in one or two files."
That talks loudly about Dunning Kruger effect of person not beaten
hard to level of elementary competence needed in our industry.
"daniel...@gmail.com" <danielaparker@gmail.com>: Jan 03 02:00PM -0800

On Sunday, January 3, 2021 at 11:36:19 AM UTC-5, Öö Tiib wrote:
> instead of using standard library, or whatever other library be it
> boost, eigen, sdl, rapidjson, ncurses and long list of others I know
> that work.
 
Most of the libraries you mention reinvent quite a few things themselves.
rapidjson reinvents float parsing, and one of the 427 items on its issues
list is a failure of exact float parsing in some cases.
 
> yourself. You can extract it and make compile-time option to use your
> extracted version as third alternative to std::basic_string_view and
> boost::basic_string_view. Does anyone want your reinvented thing?
 
Apparently. I have implementations of ns::basic_string_view, ns::optional,
and ns::span, which are part of an open source project that has been
described as "popular", and receives nice user feedback. These names
resolve to the standard library equivalents if the appropriate C++
version is detected.
 
> Who?
 
Users. But why personalize this? What difference does that make?
 
Daniel
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jan 03 10:24PM

On Sun, 2021-01-03, Öö Tiib wrote:
> high salaries so only weak specialists become teachers and at 2021
> you can easily find that majority of professional programmers fail
> miserably when attempting to implement binary search.
 
I might fail too, but at least I wouldn't deliver a broken
implementation.
 
> available implementation is] not self-contained in one or two files."
> That talks loudly about Dunning Kruger effect of person not beaten
> hard to level of elementary competence needed in our industry.
 
I did, but decided to comment only on the binary search. I'm not sure
I really want to read the OP's explanation of that. Nowaday I try to
avoid crackpot ideas, and try to remember I'm not responsible to fight
them.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
gamo <gamo@telecable.es>: Jan 03 09:17PM +0100

El 2/1/21 a las 19:12, olcott escribió:
> (a) Halts
> (b) Does Not Halt
> (c) Pathological Self Reference to Halt
 
Hello. You happen to have some insight in this problem.
In which type do you clasify te option to halt
*if* an arbitrary precision and/or repeated solution counter
reach a thresold???
 
Thank you. Best.
 
 
--
http://gamo.sdf-eu.org/
"What happens in EuroVegas it remains in EuroVegas"
gamo <gamo@telecable.es>: Jan 03 10:42PM +0100

El 3/1/21 a las 21:17, gamo escribió:
> *if* an arbitrary precision and/or repeated solution counter
> reach a thresold???
 
> Thank you. Best.
 
s/te/the/;
s/tresold/treshold/;
 
Sorry!
 
--
http://gamo.sdf-eu.org/
"What happens in EuroVegas it remains in EuroVegas"
Rosario19 <Ros@invalid.invalid>: Jan 03 06:20PM +0100

On Fri, 25 Dec 2020 10:06:28 -0500, "Rick C. Hodgin" wrote:
 
>and received up into glory where He now sits in all power and authority,
>even holding full power and authority over death, Hell, and the grave.
 
>Thanks to Jesus: "Oh death, where is thy sting?"
 
Marry Christmas, and Happy New Year to all
 
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 03 12:31PM -0800

On 1/3/2021 9:20 AM, Rosario19 wrote:
>> even holding full power and authority over death, Hell, and the grave.
 
>> Thanks to Jesus: "Oh death, where is thy sting?"
 
> Marry Christmas, and Happy New Year to all
 
Likewise! :^)
 
Bonita Montero <Bonita.Montero@gmail.com>: Jan 03 06:44PM +0100

I've just wondered why trunc() of the MSVCRT is so slow.
 
So I've written my own trunc():
 
#include <iostream>
#include <cmath>
#include <cassert>
#include <limits>
#include <vector>
#include <random>
#include <chrono>
#include <cassert>
 
using namespace std;
using namespace chrono;
 
double ftrunc( double d );
float ftrunc( float f );
 
int main()
{
union
{
double dAssemble;
struct
{
uint64_t mantissa : 52;
uint64_t exponent : 11;
uint64_t sign : 1;
};
};
mt19937_64 rg;
uniform_int_distribution<uint64_t> mantissaValues( 0, ((uint64_t)1 <<
52) - 1 );
// equal of only fractional numbers,
// mantissa with integral parts and
fractions
// and mantissa without fractions
uniform_int_distribution<unsigned> exponentValues( 0x3FF - 52, 0x3FF +
2 * 52 - 1 ),
signValues( 0, 1 );
vector<double> vd( 1'000 );
for( double &d : vd )
mantissa = mantissaValues( rg ),
exponent = exponentValues( rg ),
sign = signValues( rg ),
d = dAssemble;
for( double d : vd )
assert(ftrunc( d ) == trunc( d ));
double volatile dummyValue;
time_point<high_resolution_clock> start = high_resolution_clock::now();
size_t const turns = 1'000'000'000 / vd.size();
for( size_t i = turns; i; --i )
for( double d : vd )
dummyValue = ftrunc( d );
double ns = (double)duration_cast<nanoseconds>(
high_resolution_clock::now() - start ).count();
cout << "ftrunc: " << ns / (vd.size() * turns) << endl;
start = high_resolution_clock::now();
for( size_t i = turns; i; --i )
for( double d : vd )
dummyValue = trunc( d );
ns = (double)duration_cast<nanoseconds>( high_resolution_clock::now() -
start ).count();
cout << "trunc: " << ns / (vd.size() * turns) << endl;
}
 
double ftrunc( double d )
{
static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) not
equal to sizeof(uint64_t)");
static_assert(numeric_limits<double>::is_iec559, "double must be
IEEE-754");
// assume size_t is our CPU's native register-width
static_assert(sizeof(size_t) == sizeof(uint64_t) || sizeof(size_t) ==
sizeof(uint32_t), "register-width must be 32 or 64 bit");
if constexpr( sizeof(size_t) == sizeof(uint64_t) )
// we have 64 bit registers
{
unsigned const MANTISSA_BITS = 52,
EXP_BIAS = 0x3FF,
INF_NAN_BASE = 0x7FF;
uint64_t const EXP_MASK = (uint64_t)0x7FF
<< MANTISSA_BITS,
SIGN_MASK = (uint64_t)0x800
<< MANTISSA_BITS ,
MIN_INTEGRAL_DIGITS_EXP = (uint64_t) EXP_BIAS
<< MANTISSA_BITS,
MIN_INTEGRAL_ONLY_EXP = (uint64_t)(EXP_BIAS +
MANTISSA_BITS) << MANTISSA_BITS,
INF_NAN_EXP = (uint64_t)INF_NAN_BASE
<< MANTISSA_BITS,
NEG_MANTISSA_MASK = 0x000FFFFFFFFFFFFFu;
union
{
double du;
uint64_t dx;
};
du = d;
uint64_t exp = dx & EXP_MASK;
if( exp >= MIN_INTEGRAL_DIGITS_EXP )
// value has integral digits
if( exp < MIN_INTEGRAL_ONLY_EXP )
{
// there are fraction-digits to mask out, mask them
unsigned shift = (unsigned)(exp >> MANTISSA_BITS) - EXP_BIAS;
dx &= ~(NEG_MANTISSA_MASK >> shift);
return du;
}
else
if( exp < INF_NAN_EXP )
// value is integral
return du;
else
// infinite, NaN, SNaN
// raise exception on SNaN if necessary
return du + du;
else
{
// below +/-1.0
// return +/-0.0
dx &= SIGN_MASK;
return du;
}
}
else if constexpr( sizeof(size_t) == sizeof(uint32_t) )
// we have 32 bit registers
{
unsigned const MANTISSA_BITS = 52,
HI_MANTISSA_BITS = 20,
EXP_BIAS = 0x3FF,
INF_NAN_BASE = 0x7FF;
uint32_t const EXP_MASK = (uint32_t)0x7FFu
<< HI_MANTISSA_BITS,
SIGN_MASK = (uint32_t)0x800u
<< HI_MANTISSA_BITS,
MIN_INTEGRAL_DIGITS_EXP = (uint32_t) EXP_BIAS
<< HI_MANTISSA_BITS,
MAX_INTEGRAL32_EXP = (uint32_t)(EXP_BIAS +
HI_MANTISSA_BITS) << HI_MANTISSA_BITS,
MIN_INTEGRAL_ONLY_EXP = (uint32_t)(EXP_BIAS +
MANTISSA_BITS) << HI_MANTISSA_BITS,
INF_NAN_EXP = (uint32_t)INF_NAN_BASE
<< HI_MANTISSA_BITS,
NEG_HI_MANTISSA_MASK = 0x000FFFFFu,
NEG_LO_MANTISSA_MASK = 0xFFFFFFFFu;
union
{
double du;
struct
{
uint32_t dxLo;
uint32_t dxHi;
};
};
du = d;
uint32_t exp = dxHi & EXP_MASK;
if( exp >= MIN_INTEGRAL_DIGITS_EXP )
// value has integral digits
if( exp < MIN_INTEGRAL_ONLY_EXP )
// there are fraction-digits to mask out
if( exp <= MAX_INTEGRAL32_EXP )
{
// the fraction digits are in the upper dword, mask them and zero
the lower dword
unsigned shift = (unsigned)(exp >> HI_MANTISSA_BITS) - EXP_BIAS;
dxHi &= ~(NEG_HI_MANTISSA_MASK >> shift);
dxLo = 0;
return du;
}
else
{
// the fraction digits are in the lower dword, mask them
unsigned shift = (unsigned)(exp >> HI_MANTISSA_BITS) - EXP_BIAS -
HI_MANTISSA_BITS;
dxLo &= ~(NEG_LO_MANTISSA_MASK >> shift);
return du;
}
else
if( exp < INF_NAN_EXP )
// value is integral
return du;
else
// infinite, NaN, SNaN
// raise exception on SNaN if necessary
return du + du;
else
{
// below +/-1.0
// return +/-0.0
dxHi &= SIGN_MASK;
dxLo = 0;
return du;
}
}
}
 
float ftrunc( float f )
{
static_assert(sizeof(float) == sizeof(uint32_t), "sizeof(float) not
equal to sizeof(uint32_t)");
static_assert(numeric_limits<float>::is_iec559, "float must be IEEE-754");
unsigned const MANTISSA_BITS = 23,
EXP_BIAS = 0x7F,
INF_NAN_BASE = 0xFF;
uint32_t const EXP_MASK = (uint32_t)0xFF
<< MANTISSA_BITS,
SIGN_MASK = (uint32_t)0x100
<< MANTISSA_BITS ,
MIN_INTEGRAL_DIGITS_EXP = (uint32_t) EXP_BIAS
<< MANTISSA_BITS,
MIN_INTEGRAL_ONLY_EXP = (uint32_t)(EXP_BIAS +
MANTISSA_BITS) << MANTISSA_BITS,
INF_NAN_EXP = (uint32_t)INF_NAN_BASE
<< MANTISSA_BITS,
NEG_MANTISSA_MASK = 0x007FFFFFu;
union
{
float fu;
uint32_t fx;
};
fu = f;
uint32_t exp = fx & EXP_MASK;
if( exp >= MIN_INTEGRAL_DIGITS_EXP )
// value has integral digits
if( exp < MIN_INTEGRAL_ONLY_EXP )
{
// there are fraction-digits to mask out, mask them
unsigned shift = (unsigned)(exp >> MANTISSA_BITS) - EXP_BIAS;
fx &= ~(NEG_MANTISSA_MASK >> shift);
return fu;
}
else
if( exp < INF_NAN_EXP )
// value is integral
return fu;
else
// infinite, NaN, SNaN
// raise exception on SNaN if necessary
return fu + fu;
else
{
// below +/-1.0
// return +/-0.0
fx &= SIGN_MASK;
return fu;
}
}
 
With 32 bit code my ftrunc is 1,9 times as fast in my benchmark.
With 32 bit code it is about 4,9 times as fast in the same benchmark.
So what's the magic behind MS' trunc() implementation I miss ?
It couldn't be only that my ftrunc() is inlined and constants might
be kept in registers; I think this wouldn't make a difference like
that for the 64-bit-code.
#
Bo Persson <bo@bo-persson.se>: Jan 03 06:59PM +0100

On 2021-01-03 at 18:44, Bonita Montero wrote:
> It couldn't be only that my ftrunc() is inlined and constants might
> be kept in registers; I think this wouldn't make a difference like
> that for the 64-bit-code.
 
Are you statically linking to the C runtime, or are you calling a
DLL-version of the function?
 
 
 
Bo Persson
Bonita Montero <Bonita.Montero@gmail.com>: Jan 03 07:00PM +0100

> With 32 bit code my ftrunc is 1,9 times as fast in my benchmark.
> With 32 bit code it is about 4,9 times as fast in the same benchmark.
64
Bonita Montero <Bonita.Montero@gmail.com>: Jan 03 07:01PM +0100

>> that for the 64-bit-code.
 
> Are you statically linking to the C runtime, or are you calling a
> DLL-version of the function?
 
Wouldn't make a big difference until the code doesn't become inlined.
But even then, it bet it wouldn'T 4,9 times faster.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 03 07:14PM +0100

> Are you statically linking to the C runtime, or are you calling a
> DLL-version of the function?
 
I just tested it with linking it with /MT and /MD. The statically
linked version is 21% slower; I would have expected the opposite
if ever there's a difference.
Juha Nieminen <nospam@thanks.invalid>: Jan 03 09:32AM

> My point was that std::array is no less efficient that a plain array
> when used as one.
 
Also, like with other standard library containers, you'll get debug boundary
checking with gcc (and probably clang) if you compile with the option
-D_GLIBCXX_DEBUG, which you won't get for inbuilt arrays.
 
(Ok, I didn't actually check that -D_GLIBCXX_DEBUG also affects std::array,
but I would be very surprised if it didn't.)
 
(And yes, I'm aware of -fsanitize=address which ought to detect
out-of-bounds accesses of inbuilt arrays as well, but AFAIK it's not
as reliable, because with standard library containers and -D_GLIBCXX_DEBUG
the checks are added to the indexing code itself, checking against the
size of the array.)
"Öö Tiib" <ootiib@hot.ee>: Jan 03 07:47AM -0800

On Saturday, 2 January 2021 at 18:42:21 UTC+2, David Brown wrote:
> that starts at one number, then increments or decrements until it
> reaches a target - but it is extremely common. Optimisations and static
> analysis that make use of such situations are therefore useful.
 
Note that vast majority of for loops in modern code are range-based
fors of C++11. So compiler already knows compile-time what that
range of std::array is. It has embarrassingly no ways to break that range
and so has no need to check it neither compile nor run time.
spudisnotyourbud@grumpysods.com: Jan 03 04:23PM

On 2 Jan 2021 19:00:15 GMT
>"why?": as far as I'm concerned, std::array is (since 2011) the
>default tool for fixed-size arrays. It's the /other/ solutions that
>need a motivation.
 
"In my opinion" is not an answer to Why.
spudisnotyourbud@grumpysods.com: Jan 03 04:27PM

On Sun, 3 Jan 2021 10:08:44 +1300
 
>Clearly it doesn't. That's why std::array has at().
 
>My point was that std::array is no less efficient that a plain array
>when used as one.
 
And also brings nothing to the table when dealing with fixed sized arrays
where no bounds checking needs to be done except probably binary bloat.
"Öö Tiib" <ootiib@hot.ee>: Jan 03 09:09AM -0800

> >when used as one.
> And also brings nothing to the table when dealing with fixed sized arrays
> where no bounds checking needs to be done except probably binary bloat.
 
The raw array brings nothing to table. Nothing. Have to
lose the size information or to use that uint8_t (*foo)[42] crap to pass
reference to it or have to wrap it into struct to pass by value. If done so
there are still no advantages, still as error-prone and ugly as it was.
Only excuse of advocating its usage is that you had the pain of using
it and want others to have same pain. IOW sadism of pathetic asshole.
spuddy@isnotyourbuddy.co.uk: Jan 03 05:22PM

On Sun, 3 Jan 2021 09:09:00 -0800 (PST)
>> And also brings nothing to the table when dealing with fixed sized arrays
>> where no bounds checking needs to be done except probably binary bloat.
 
>The raw array brings nothing to table. Nothing. Have to
 
Bringing something to the table implies something more than already existed.
The raw array is what already existed so by definition it wouldn't.
 
>lose the size information or to use that uint8_t (*foo)[42] crap to pass
>reference to it or have to wrap it into struct to pass by value. If done so
>there are still no advantages, still as error-prone and ugly as it was.
 
A MAC is fixed size, it NEVER changes. There is no need for anything other than
a C array.
 
>it and want others to have same pain. IOW sadism of pathetic asshole.
 
Ad homenim - the last resort of someone with no argument. Nice going.
 
Oh, and its spelt ARSEhole unless you're speaking in the american dialect.
"Öö Tiib" <ootiib@hot.ee>: Jan 03 09:44AM -0800


> >The raw array brings nothing to table. Nothing. Have to
> Bringing something to the table implies something more than already existed.
> The raw array is what already existed so by definition it wouldn't.
 
So there are no reasons to return to it ever as it has no advantages whatsoever.
 
> >there are still no advantages, still as error-prone and ugly as it was.
> A MAC is fixed size, it NEVER changes. There is no need for anything other than
> a C array.
 
Compiler has no concept of MAC. The std::array is in every sense as good or
better array than C array, also for MAC.
 
> >it and want others to have same pain. IOW sadism of pathetic asshole.
> Ad homenim - the last resort of someone with no argument. Nice going.
 
> Oh, and its spelt ARSEhole unless you're speaking in the american dialect.
 
You failed to show any other motivation of pushing inferior choice so I
guessed correctly? 😀 OK I can call you "pathetic arsehole" if you so wish.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jan 03 06:13PM

>>default tool for fixed-size arrays. It's the /other/ solutions that
>>need a motivation.
 
> "In my opinion" is not an answer to Why.
 
Correct. I'll reformulate:
 
I know there's been a long discussion about this, but to address the
"why?": as far as I'm concerned, std::array is (since 2011) the
default tool for fixed-size arrays. It's the /other/ solutions that
need a motivation.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Brian Wood <woodbrian77@gmail.com>: Jan 02 04:09PM -0800

On Saturday, January 2, 2021 at 8:41:18 AM UTC-6, Öö Tiib wrote:
> attempts of cheating). No way I would let anyone identify
> themselves for reading my site or for downloading and trying
> something I said is free to try there.
 
I'm not asking anyone to identify themselves for reading my
site or downloading my open-source software. If you want
to use my closed-source software, you have to have an
account.
 
> his stuff so badly to make account? FlatBuffers do not require
> me to make account. Probably it is some kind of scam to get
> my e-mail or something and then spam me.
 
I've been on this list for over 16 years and have been improving
my software. We could, for example, go back to the first commits
of my repo and compare how long it takes to build then and now,
the sizes of the executables then and now, the additional
functionality, etc.
 
I believe having some closed-source software (private property)
is the way to go.
 
> Should I
> manufacture some false, throw-away identity to try his
> garbage? Yuck.
 
Feel free to point out some weaknesses. My FixedVector
class is new and it needs some help.
 
I think these programs are in fairly good shape:
https://github.com/Ebenezer-group/onwards/blob/master/src/tiers/genz.cc
https://github.com/Ebenezer-group/onwards/blob/master/src/tiers/cmwA.cc
 
Only been working on them for 11 years.
 
 
> See, you have already lost by asking for account.
 
Providing a SaaS was a great idea when I started and still is.
Building a (walled) garden is a privilege and adventure. I hope
to continue to grow into these areas: cross-platform,
middleware, network-programming, serialization,
messaging, managed-services.
 
 
Brian
Ebenezer Enterprises - Enjoying programming again.
https://webEbenezer.net
"Öö Tiib" <ootiib@hot.ee>: Jan 03 07:34AM -0800

> On Saturday, January 2, 2021 at 8:41:18 AM UTC-6, Öö Tiib wrote:
 
Read again:
 
> functionality, etc.
 
> I believe having some closed-source software (private property)
> is the way to go.
 
We are not talking about you, we are talking about your potential
customers who do not know you nor care about you.

> > garbage? Yuck.
> Feel free to point out some weaknesses. My FixedVector
> class is new and it needs some help.
 
I haven't even tried to use it. Only looked into code. Code
like all the other millions of lines of code I've seen. Problem
of none of programmers is that they lack code for something.
There is usually annoyingly long list of choices instead.
So what matters are benefits, downsides and effort needed
to use one or other in that long list. You have made the item
that you name "middleware writer" tiresome to even evaluate
if it has any benefits whatsoever in that pile of inconveniences
so it never enters that list of choices of smart and
hard-working people.

> https://github.com/Ebenezer-group/onwards/blob/master/src/tiers/genz.cc
> https://github.com/Ebenezer-group/onwards/blob/master/src/tiers/cmwA.cc
 
> Only been working on them for 11 years.
 
Yes, people do not care about you or your code. I said
"Throw that away, no one cares. That part only makes it hard for
you to make successful things. Care about convenience and
benefit of others." Only if you ever cared about others for just
a bit there is chance that they start to care about whatever
you have made.

> to continue to grow into these areas: cross-platform,
> middleware, network-programming, serialization,
> messaging, managed-services.
 
Yes, and people do not care about you, your code or your
"walled garden". Think why you fought edit war of Wikipedia
with Leigh? You wanted to advertise your "walled garden" so
people would come to see it. Why? Why you spam about thing
no one wants to see? May be few wanted to see it ever. No
one of these few has said that they did like what they saw.
It is because you did not care about them but about yourself.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: