Thursday, July 21, 2016

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

Paavo Helde <myfirstname@osa.pri.ee>: Jul 21 04:35PM +0300

This came up during code refactoring. Let's assume I have a function
taking a reference to a base class object, say
 
void foo(Base&);
 
What would be the best way to refuse compilation when a derived class
object is passed instead? (I am needing this to avoid logical constness
leaking problems in a callback scenario, if anybody is curious).
 
There are other functions where passing both Base and Derived is needed
and is perfectly OK, the prohibition should appear only for foo() only.
 
My first attempt on this only reports a linker error, which is not
enough as it does not provide the location of the invalid call (and
there are thousands of those calls in the codebase). I would prefer to
get a compiler error at the line marked "NOT OK":
 
class Base {};
class Derived: public Base {};
 
void foo(Base& ref) {}
 
void foo(Derived&); // not implemented
 
int main() {
Derived der1;
foo(der1); // compiling, NOT OK!
}
 
TIA
Paavo
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 21 03:19PM +0100

On Thu, 21 Jul 2016 16:35:24 +0300
> Derived der1;
> foo(der1); // compiling, NOT OK!
> }
 
If you want a compile time assertion rather than a run-time one, I
think you will have to templatize it and apply static_assert to the
result of applying std::is_same to the type passed in.
 
Chris
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 21 06:22PM +0200

On 21.07.2016 15:35, Paavo Helde wrote:
> class Derived: public Base {};
 
> void foo(Base& ref) {}
 
> void foo(Derived&); // not implemented
 
Make that
 
void foo( Derived& ) = delete;
 
to get diagnostics at compile time rather than link time.
 
 
> Derived der1;
> foo(der1); // compiling, NOT OK!
> }
 
The approach won't catch Base references where the most derived class is
something derived from Base.
 
And you can't do that statically.
 
One way to do that at runtime is to make Base a polymorphic class, and
`assert( typeid( object ) == typeid( Base ) )`.
 
That said, this all has a certain odour.
 
But dealing with constness in callbacks is notoriously difficult.
 
 
Cheers & hth.,
 
- Alf
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jul 21 05:47PM +0100

On 21/07/2016 14:35, Paavo Helde wrote:
> Derived der1;
> foo(der1); // compiling, NOT OK!
> }
 
What you are trying to do breaks the Liskov substitution principle so is
the wrong approach; try to solve your problem some other way.
 
/Flibble
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 21 06:11PM +0100

On Thu, 21 Jul 2016 18:22:35 +0200
 
> Make that
 
> void foo( Derived& ) = delete;
 
> to get diagnostics at compile time rather than link time.
 
How interesting. I didn't know you could delete functions which are
not class member functions in order to prevent unwanted implicit
conversions. I guess it works because the deleted function still
participates in overload resolution.
 
I am not sure I would want to do that often, but it is nice to know.
Paavo Helde <myfirstname@osa.pri.ee>: Jul 21 10:21PM +0300

On 21.07.2016 19:22, Alf P. Steinbach wrote:
 
> Make that
 
> void foo( Derived& ) = delete;
 
> to get diagnostics at compile time rather than link time.
 
Wow, that looks exactly what I wanted! And it seems it is even supported
by my target compilers!
 
Another approach what I came up with meanwhile was to make foo( Derived&
) an inaccessible private member function. But "=delete" feels cleaner
(documents the intent better).
 
Thanks!
Paavo
Paavo Helde <myfirstname@osa.pri.ee>: Jul 21 11:06PM +0300

On 21.07.2016 19:47, Mr Flibble wrote:
>> }
 
> What you are trying to do breaks the Liskov substitution principle so is
> the wrong approach; try to solve your problem some other way.
 
The Liskov principle does not work here because there is a callback
mechanism involved. A class is supposed to register a bunch of Base
object addresses (via the function similar to foo() above). The engine
later stores some Base objects there and calls back a virtual function
of the class to process them.
 
Now if the class registered Derived class objects instead of Base class
objects, the stored objects would be actually of a wrong type (not so
big deal in my case as this would just mean some loss of const
correctness, but still).
 
The data cannot be passed via the normal virtual function parameters
because there are many different types involved and the number of
potential signatures is large. Passing an array of some Variant type
would work, but this would make the class code clumsier and more fragile
than necessary.
 
Cheers
Paavo
ram@zedat.fu-berlin.de (Stefan Ram): Jul 21 07:08PM

>Make that
>void foo( Derived& ) = delete;
>to get diagnostics at compile time rather than link time.
 
If I understand it correctly, this only would delete the
call for the /specific/ derived type given. I tried to
forbid /every/ derived type using a *cough*macro*cough*.
 
#include <iostream>
#include <ostream>
#include <string>
#include <type_traits>
 
using namespace ::std::literals;
 
class Base {};
 
class Derived : public Base {};
 
void g( Base ) {}
 
#define f(x) \
static_assert\
(::std::is_same<decltype(x),Base>::value,\
"argument of f must have Base type"); \
g(x);
 
int main()
{ { Base b; f( b ); }
{ Derived d; f( d ); }}
 
Ok, I seem to have ignored that it should be a reference,
but it might be possible to modify this for references.
ram@zedat.fu-berlin.de (Stefan Ram): Jul 21 07:19PM

>g(x);
>Ok, I seem to have ignored that it should be a reference,
>but it might be possible to modify this for references.
 
What I wrote, checks the type of the expression »x«, not of
a referred object.

When the object is supplied by a pointer that has a type
of »pointer to base« but can point to a derived object
at runtime, the compiler can't check this, because the
compiler cannot see runtime object.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 21 01:18AM +0100

On Wed, 20 Jul 2016 15:53:10 -0700 (PDT)
 
> Ouch. That sort of detachment from reality has led
> to so many messes in the standard. I think Jerry is
> just highlighting another one here.
 
Brian, you have turned into a kind of random garbage generator.
 
An aggregate is special because it permits aggregate initialization.
That is relevant because aggregate initialisation mimics C
initialization. The comments Jerry made about encapsulation would have
been fair enough if aggregates include any struct or class, such as
those having private members. But they do not.
 
This is not surprising. There are other C related special types, in
particular trivial classes, which can be statically initialized, and
standard layout classes, which are consistent with the C memory layout
of structs and unions.
 
Your position is worse than Jerry's. He made an understandable
mistake. You however have had the benefit of having the point about
aggregates explained to you in other posts and you still manage to miss
the point.
 
But to give you another chance, could you now explain what "detachment
from reality" you think the C++ standard contains and what "messes" you
think need correction. Given that you think you have some kind of
messianic call with respect to leadership of C++ (see your ridiculous
post at
http://comp.lang.cpp.narkive.com/q0Yuq9Cf/comments-on-interview-of-scott-meyers
) I imagine you have your analysis pre-prepared for us to read.
Jerry Stuckle <jstucklex@attglobal.net>: Jul 20 10:59PM -0400

On 7/20/2016 4:45 PM, Ian Collins wrote:
 
> class C { int n; } c {0}; // Not an aggregate
> class S { public: int n; } s {0}; // Aggregate
 
> Happy now?
 
Nope. Class S does not contain variables with different data types.
 
And it violates encapsulation rules.
 
But I know you're an trolling idiot, so no surprise here.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Jul 20 11:01PM -0400

On 7/20/2016 6:59 PM, Ian Collins wrote:
> definitions and promote a free for all?
 
>> I think Jerry is just highlighting another one here.
 
> Jerry is being an arse.
 
You are just being a stoopid troll. As usual. But that's not
surprising. Idiots are often like that.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Jul 20 11:02PM -0400

On 7/20/2016 5:30 PM, Gareth Owen wrote:
 
> Yes, but did Bjarne ever work as a consultant for IBM? Eh? Eh?
 
> No.
 
> So what does he know.
 
Envy will never get you anywhere. Just because you can't get a job with
a decent company is not my problem.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Ian Collins <ian-news@hotmail.com>: Jul 21 03:08PM +1200

On 07/21/16 02:59 PM, Jerry Stuckle wrote:
>> class S { public: int n; } s {0}; // Aggregate
 
>> Happy now?
 
> Nope. Class S does not contain variables with different data types.
 
So?
 
class S { public: int n; char c; } s {0,'a'}; // Aggregate
 
Now it does, not that this makes any difference.
 
> And it violates encapsulation rules.
 
So? It's what C++ calls an aggregate.
 
> But I know you're an trolling idiot, so no surprise here.
 
Ah good, back to juvenile insults. Didn't take long this time, did it?
 
--
Ian
Jerry Stuckle <jstucklex@attglobal.net>: Jul 20 11:18PM -0400

On 7/20/2016 11:08 PM, Ian Collins wrote:
 
>> Nope. Class S does not contain variables with different data types.
 
> So?
 
> class S { public: int n; char c; } s {0,'a'}; // Aggregate
 
Look at your definition of aggregate. You're too stoopid to even know
you're wrong.
 
> Now it does, not that this makes any difference.
 
According to YOUR definition, it does. But you're too stoopid to
understand something so simple.
 
>> And it violates encapsulation rules.
 
> So? It's what C++ calls an aggregate.
 
Which violates a basic precept of OO. But you're too stoopid to
understand that.
 
>> But I know you're an trolling idiot, so no surprise here.
 
> Ah good, back to juvenile insults. Didn't take long this time, did it?
 
Actually, calling you an idiot is an insult to idiots.
 
But the truth hurts, doesn't it?
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Ian Collins <ian-news@hotmail.com>: Jul 21 03:42PM +1200

On 07/21/16 03:18 PM, Jerry Stuckle wrote:
 
>> So?
 
>> class S { public: int n; char c; } s {0,'a'}; // Aggregate
 
> Look at your definition of aggregate.
 
Not mine, it is the C++ standard's definition.
 
C++ is something known as a programming language which has an
international standard which defines the terms C++ programmers use when
discussing their language of choice.
 
C++ is the topic of this group.
 
--
Ian
Jerry Stuckle <jstucklex@attglobal.net>: Jul 21 10:22AM -0400

On 7/20/2016 11:42 PM, Ian Collins wrote:
> international standard which defines the terms C++ programmers use when
> discussing their language of choice.
 
> C++ is the topic of this group.
 
Gee, I couldn't tell.
 
Unlike you, I'm not stoopid. But my customers (and I) hire programmers.
You wouldn't even get an interview.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jul 21 05:50PM +0100

On 21/07/2016 04:42, Ian Collins wrote:
> international standard which defines the terms C++ programmers use when
> discussing their language of choice.
 
> C++ is the topic of this group.
 
Ian, it seems obvious to me that Jerry Stuckle is a fucktarded troll so
why do you engage it?
 
/Flibble
hdreck@freenet.de: Jul 21 04:20AM -0700

I inspect some code which works with Intel icpc, but seems to
be time-bomb if compiled with g++.
It swaps two arrays like thus:
tmp=array1;
array1=array2;
array2=tmp;
 
array1 and array2 were allocated this way:
array1=(int *)malloc (4*size);
 
tmp is not allocated, it is merely:
int *tmp;
 
Now I am curious how compiler would know to copy "size" words
then stop. Apparently Intel can, but g++ cannot, so corrupts
adjacent memory, and the free() for a later malloc has invalid pointer.
JiiPee <no@notvalid.com>: Jul 21 12:37PM +0100

> int *tmp;
 
> Now I am curious how compiler would know to copy "size" words
> then stop.
 
"copy" - are you talking about this:
 
array1=array2;
which copy are you talking about?
 
 
 
"Fred.Zwarts" <F.Zwarts@KVI.nl>: Jul 21 03:06PM +0200

schreef in bericht
news:1c6f603b-7200-4527-ad73-b3f248b80ff7@googlegroups.com...
 
>Now I am curious how compiler would know to copy "size" words
>then stop. Apparently Intel can, but g++ cannot, so corrupts
>adjacent memory, and the free() for a later malloc has invalid pointer.
 
You did not show a compilable program, nor the declarations of array1 and
array2.
If they are int * pointers, than not the arrays are swapped in this code,
but the pointers to the arrays are swapped.
This is not a problem for any compiler.
How do you know that adjacent memory is corrupted?
Because of swapping pointers, it could also be that one array is not freed
and the other one is freed twice.
D Laboratory <dlaboratory@126.com>: Jul 21 09:58PM +0800


> Now I am curious how compiler would know to copy "size" words
> then stop. Apparently Intel can, but g++ cannot, so corrupts
> adjacent memory, and the free() for a later malloc has invalid pointer.
 
You did not copy the array. You just swapped the pointers.
Jerry Stuckle <jstucklex@attglobal.net>: Jul 21 10:28AM -0400


> Now I am curious how compiler would know to copy "size" words
> then stop. Apparently Intel can, but g++ cannot, so corrupts
> adjacent memory, and the free() for a later malloc has invalid pointer.
 
You're not copying the array itself. What you are doing is swapping the
addresses of the two arrays. Try displaying the pointers before and
after the swap, and you'll see what I mean.
 
It's like switching the addresses on two apartments, so that apartment
1A is now apartment 1B, and vice versa. You haven't moved the families,
furniture, or anything except the numbers on the doors. But now mail
going to apartment 1A ends up in a different family.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
JiiPee <no@notvalid.com>: Jul 21 03:35PM +0100

On 21/07/2016 14:58, D Laboratory wrote:
>> then stop. Apparently Intel can, but g++ cannot, so corrupts
>> adjacent memory, and the free() for a later malloc has invalid pointer.
 
> You did not copy the array. You just swapped the pointers.
 
thats what i was also thinking
Juha Nieminen <nospam@thanks.invalid>: Jul 21 02:30PM

>> constexpr Test kTest2 = B { 5, 10, { 1, 2, 3 } };
 
> I think clang is correct. { 1, 2, 3 } is a temporary initializer_list
> object.
 
If that's so, why doesn't it complain about the kB initialization?
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
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: