- Prohibit calling a function with a derived class object - 7 Updates
- Prohibit calling a function with a derived class object - 2 Updates
- Why not designated initializers in C++? - 9 Updates
- array shorthand in c++ (how safe?) - 6 Updates
- initializer_list member and constexpr - 1 Update
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:
Post a Comment