Sunday, October 21, 2018

Digest for comp.lang.c++@googlegroups.com - 13 updates in 3 topics

"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Oct 21 08:56AM +0200

#include <iostream>
 
template< class Item >
auto operator,( std::ostream& stream, const Item& item )
-> std::ostream&
{
return (stream << item);
}
 
auto main()
-> int
{
using namespace std;
cout << "Did you know, 6*7 = ", 6*7, "! :)\n";
}
 
Cheers!,
 
- ALf
Ralf Goertz <me@myprovider.invalid>: Oct 21 10:58AM +0200

Am Sun, 21 Oct 2018 08:56:52 +0200
> }
 
> Cheers!,
 
> - ALf
 
Nice. But the output
 
Did you know, 6*7 = 42! :)
 
is false since
 
42! =1405006117752879898543142606244511569936384000000000
 
SCNR
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Oct 21 05:34PM +0100

On 21/10/2018 07:56, Alf P. Steinbach wrote:
>     }
 
> Cheers!,
 
> - ALf
 
Egregious for various reasons.
 
/Flibble
 
--
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who
doesn't believe in any God the most. Oh, no..wait.. that never happens." –
Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."
woodbrian77@gmail.com: Oct 21 09:52AM -0700

On Sunday, October 21, 2018 at 1:57:03 AM UTC-5, Alf P. Steinbach wrote:
> #include <iostream>
 
> template< class Item >
> auto operator,( std::ostream& stream, const Item& item )
 
I suggest you add a space after function/operator names.
 
 
Brian
Ebenezer Enterprises - Enjoying programming again
https://github.com/Ebenezer-group/onwards
Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Oct 21 07:01PM -0400

Alf P. Steinbach wrote:
>     }
 
> Cheers!,
 
> - ALf
 
I use this trick in one of my logging libraries before variadic templates became
available, something to the form
 
log(logRecord, "did you know", ...);
 
`log' does actual formatting and flushing, `logRecord' just collects a list of
loggable items to include into the log record. This way you never forget to
flush the log and you can pass a log record to a function that does not
necessarily logs by that saving you unnecessary formatting (handy when you only
want to work on error).
 
my 2c
-Pavel
Sam <sam@email-scan.com>: Oct 21 08:28AM -0400

Paul writes:
 
 
> AndSpecification(const Specification<T>& first, const Specification<T>&
> second)
> : first(first), second(second) {}
 
You're grabbing references to these parameters and storing them in this
(template) class.
 
> auto spec2 = SizeSpecification(Size::large)&&
> ColorSpecification(Color::green);
 
You are constructing an instance of the AndSpecification template, using the
&& operator overload.
 
Both "SizeSpecification(Size::large)" and "ColorSpecification(Color::green)"
are temporary objects here, that get created when evaluating this expression.
 
And immediately destroyed after the expression gets evaluated.
 
Your instance of the AndSpecification template, thusly, ends up having
references to destroyed objects. They certainly exist when AndSpecification
gets constructured, and its constructor gets valid references to them. But
because the referenced objects are temporary objects, they get destroyed
soon thereafter.
 
Explicitly instantiating everything should work:
 
auto large=SizeSpecification(Size::large);
auto green=SizeSpecification(Size::green);
 
auto spec2 = large && green;
 
Now, both large and green objects will exist as long as the "spec2" object
exists, so the references to them, in spec2, remain valid.
 
Of course, this is not as convenient. But this is how your templates are
designed. Basically, if you store a reference somewhere, it's your
responsibility to make sure that the referenced objects still exist every
time you use that referenced object. C++ will not do it for you.
 
The only way to make sure that the object exist is store the object itself,
and not a reference to it. This is impossible to do, in your situation,
because the object themselves are abstract base classes.
 
The most common way this kind of concept gets implemented is with smart
pointers. And plenty of overloading.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 21 02:37PM

On Sun, 2018-10-21, Sam wrote:
>> or something.
>> Please could someone explain exactly what the problem is?
>> Thank you.
 
(snip detailed explanation)
 
> because the object themselves are abstract base classes.
 
> The most common way this kind of concept gets implemented is with smart
> pointers. And plenty of overloading.
 
For perspective, I note that it's all massive overkill in this
specific case, which is about finding the large, green objects in a
sequence.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 21 02:41PM

On Sat, 2018-10-20, Paul wrote:
> or something.
> Please could someone explain exactly what the problem is?
> Thank you.
...
 
> Product tree{"Tree", Color::green, Size::large};
> Product house{"House", Color::blue, Size::large};
> const vector<Product*> all { &apple, &tree, &house };
 
Unrelated to your problem, I suppose, but avoid storing pointer in
containers, when you can store the objects themselves:
 
const vector<Product> all {
{"Apple", Color::green, Size::small},
{"Tree", Color::green, Size::large},
{"House", Color::blue, Size::large},
};
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Paul <pepstein5@gmail.com>: Oct 21 08:12AM -0700

On Sunday, October 21, 2018 at 3:41:38 PM UTC+1, Jorgen Grahn wrote:
> {"Tree", Color::green, Size::large},
> {"House", Color::blue, Size::large},
> };
 
These are dummy examples for the purposes of learning good technique.
I thought that, assuming a real-world example where the Product struct
would be much more complicated, then storing pointers saves memory.
Am I wrong?
 
Thanks a lot for your help,
 
Paul
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 21 06:58PM

On Sun, 2018-10-21, Paul wrote:
>> {"House", Color::blue, Size::large},
>> };
 
> These are dummy examples for the purposes of learning good technique.
 
As you may have sensed already ;-) I have issues with that strategy.
 
I understand that learning techniques is necessary, eventually. But
picking simple (yet synthetic) examples and applying advanced
solutions may teach you to overdesign things which should be simple.
 
A technique is only good in a context where it's fitting.
 
> I thought that, assuming a real-world example where the Product struct
> would be much more complicated, then storing pointers saves memory.
> Am I wrong?
 
Yes. Why would it save memory? Nowadays it doesn't even avoid a
copy, since you can construct the Product straight into the
std::vector<Product>.
 
The generic name "Product" made me think you eventually meant to have
it as a base class and derive Apple, Tree and House from it. In that
case you couldn't have a std::vector<Product>, and storing pointers
would be one solution. Even then, I think people would recommend a
vector of smart pointers instead.
 
(On the other hand, I don't think that would be a very realistic class
hierarchy. If you see everything as a product, you don't care if it's
an apple, and it won't have any apple-specific behavior. You may care
if a products can be shipped to Australia, can be frozen or be stored
for a year instead.)
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Oct 21 01:53AM +0200

On 20.10.2018 20:45, Manfred wrote:
>       *outIt++ = OutputIterator::traits_type::to_char_type('0' + d.rem);
>     }
>   }
 
The C++ standard guarantees that the decimal digits are consecutive.
 
There's no such guarantee for the English letters.
 
Since I like things simple and robust I don't like this function: it
relies too much on client code supplying a safe output iterator, and the
recursive call will most probably not be optimized out, so, inefficient.
 
But then I don't like the C++17 standard library solution either, the
`std::to_chars` function
(https://en.cppreference.com/w/cpp/utility/to_chars). They boast that
"std::to_chars is locale-independent, non-allocating, and non-throwing".
But that's basic requirements.
 
In particular there is apparently no way to compute a required buffer
size. If so then that's kind of über-silly. IMHO.
 
When the time comes where all common compilers support `std::to_chars`
one can write some simple wrappers. Maybe that time has already come, a
month or two ago. Not sure, I haven't checked.
 
 
Cheers!,
 
- Alf
Manfred <noname@add.invalid>: Oct 21 05:26PM +0200

On 10/21/2018 1:53 AM, Alf P. Steinbach wrote:
>>      }
>>    }
 
> The C++ standard guarantees that the decimal digits are consecutive.
Good remark, thanks!
 
 
> Since I like things simple and robust I don't like this function: it
> relies too much on client code supplying a safe output iterator, and the
> recursive call will most probably not be optimized out, so, inefficient.
In fact in all of the code I posted there is absolutely no error
checking - which makes it inapt for anything else than a post example.
 
I believe the recursive call cannot be optimized out, since output must
occur /after/ the recursion.
This is a direct consequence that the digits have to be output in
reverse order with respect to the div() sequence.
In this respect I am not sure it is /that/ inefficient, it basically
replaces allocation of a (possibly growing) string buffer with a call
sequence on the stack. I guess in general the latter is more efficient
than the former.
There are most probably better solutions, though..
 
Manfred <noname@add.invalid>: Oct 21 06:19PM +0200

On 10/21/2018 12:11 AM, Pavel wrote:
> Neat solution, BTW. I like your recursive encodeDecimal, very haskellish. There
> is no need to compare inIt to endIt more than once though.
 
Yes, nor there is need to dereference inIt more than once, so that a
couple of local variables would be in order.
Also, an option could be to have encodeDecimal as a recursive lambda.
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: