Like Tree9Likes

Newbie Syntax Question (Start of subroutine)

This is a discussion on Newbie Syntax Question (Start of subroutine) within the C++ Programming forums, part of the General Programming Boards category; I am not backpedalling. I mentioned delete what you new because obviously I did not know Qt does something as ...

  1. #16
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    I am not backpedalling.
    I mentioned delete what you new because obviously I did not know Qt does something as insane as automatically destroying objects because it isn't self documenting.
    Sure, I could have read about how Qt works and I would have known. But I didn't, because I do not work with Qt and haven't really used it much.
    I did not say anything else, nor do I have any intention of doing so.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #17
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,415
    I'm saying it's not self-documenting.
    O_o

    The convenience of self-registration outweighs the cons when properly implemented.

    If you know the API is self-registering, it is self-documenting.

    I mentioned delete what you new because obviously I did not know Qt does something as insane as automatically destroying objects because it isn't self documenting.
    Do you really not realize that the facility in question is acting as a collection of smart pointers with a strict owner?

    It is, very literally, a variant of the mechanism employed by the "Boost Pointer Container Library" which I know you love.

    The only difference is that this facility, as implemented, uses inheritance based polymorphisms without support of template based polymorphisms.

    The act of creating the object in question as a child of another object is only registering the child object with the container.

    Now, you didn't know the API is self-registering; none has faulted you for not knowing.

    However, the mechanism at play is very useful and has few negatives.

    Again, I appreciate that this is a "knee-jerk" reaction, but like the other things you've grown from in the past, this is something you should put in your toolbox.

    [Edit]
    If you are having difficult understanding the value of self-registration, feel free to continue reading.

    If you already understand the value, you should probably just have a cookie.

    Code:
    Button s(this));
    What happens when `s' goes out of scope? If `s' is a value type, it living beyond its scope is repellent. The `new' object at least is expected to live beyond the pointer's scope.

    We can conquer this by requiring that `s' live beyond the implied scope.

    Code:
    class MyWidget
    // ...
    Button m; //m(this);
    // ...
    We still have the same problem of managing ownership.

    The `MyWidget' instance owns any `m', but the abstraction of underlying facilities requires that `m' be referenced by the underlying primitives.

    We can conquer this by using a shared pointer.

    Code:
    class MyWidget
    // ...
    Pointer<Button> m; //m(new Button(this));
    // ...
    There is now the issue of lifetime in relation to events that must be considered: if the widget represented by `MyWidget' is destroyed, for example say by the user clicking a "close" button, should the GUI resourced owned by `m' not be reclaimed by the system?

    (This could be done without destroying the object, but a function and object would still need to be registered as a callback using any available mechanism.)

    We can conquer this by moving ownership to a registry.

    Code:
    Widget * s(CraftWidget<Button>(this));
    In standard ISO C++, at least before more of C++11 is readily available to the majority of clients, we don't have a good way of forwarding arbitrary information to the `Widget' without borrowing heavily from factory techniques.

    We can conquer this by moving passing a pointer to a new element to the registry.

    Code:
    RegisterWidget(this, new Button(/*???*/));
    We now need to query the registry to retrieve the object we just created or store the object separately.

    Code:
    Button * s(new Button(/*???*/));
    RegisterWidget(this, s);
    We now have a process requiring multiple parts so we can't easily use the facility as part of the initialize list.

    We can conquer this by return a pointer to the created item as part of the registration.

    Code:
    Button * s(static_cast<Button>(RegisterWidget(this, new Button(/*???*/))));
    We now have to duplicate the type information.

    We can conquer this with ISO C++98 templates.

    Code:
    Button * s(RegisterWidget<Button>(this, new Button(/*???*/)));
    Oh, wait, we actually can't get rid of the duplicate type information and still allow for arbitrary construction with C++98 templates.

    The best we could do is allow a fixed set of parameters and simply forward them, process a list of types and forward the expansion (which is valid even with inheritance based polymorphisms because it is the constructor we are making a template), or use a serialization, like "JSON", for all construction information.

    We also can't conquer this without templates.

    Code:
    Button * s(static_cast<Button>(this->registerWidget(new Button(/*???*/))));
    Here we are back to having duplicate type information.

    *shrug*

    I could go on for much longer than anyone would read.

    The point is: performing an action related to an object provided as part of construction, managing resources as a list of resources, strict ownership, and smart pointers are all perfectly valid.

    They are not less valid, or less useful, simple because they've been used together.
    [/Edit]

    Soma

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    Quote Originally Posted by phantomotap View Post
    The point is: performing an action related to an object provided as part of construction, managing resources as a list of resources, strict ownership, and smart pointers are all perfectly valid.

    They are not less valid, or less useful, simple because they've been used together.
    I don't disagree with you. I'm not saying that Qt is built in a bad way (although looking at it from a C++11 perspective, perhaps it was; but then again, it was built before C++11, so we really can't fault it).
    What I am saying is regardless of how you look at it, the interface is not self documenting. It would have been easy just to create a simple container that implicitly delegates that information, such as do_not_delete<T>. If we did that, then the interface would easily tell us what we needed to know: should we delete this pointer later on?
    Or perhaps a better name is auto_deleter<T>, some kind of homegrown smart pointer. This very nicely conveys the message that the encapsulated pointer will automatically be deleted (we don't need to know how).
    As a bonus, if we'd look at the documentation, we'd see that it wants an auto_deleter<T>. So we check that type because we need to know how to construct it, and it would explicitly convey the information we need: create an object on the heap and do not delete it.

    If I see a raw pointer somewhere, I immediately begin to ask myself: should I delete this, or should I not?
    In all of my own code, I try to make it self documenting like this. I take references in the interface, and if I have to take a pointer, then I'll be sure to use a smart pointer.
    If I have a pointer member in my class, I either make it a smart pointer if I need to delete it, or if I don't, I use a raw pointer and attach a // DO NOT DELETE comment to ensure it's self documenting.

    All I'm saying is that Qt could have been more self documenting, in addition to self-registering if need be, and if it had, this little "oversight" that started this conversation could probably have been avoided.
    Imagine getting used to some new big system with tons of different libraries/parts. You are bound to make tons of mistakes because you don't know whether it's "self registering" or not before you can get used to everything.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    Mmm, but then we come back to the fact that Qt is doing something that a lot of GUI packages do, and you are expected to read the documentation/know it well enough to understand the code. A lot of things are not necessarily self documenting (inheritence and initializer lists use the same syntax token but they have different semantics).

  5. #20
    Registered User TangoOversway's Avatar
    Join Date
    Mar 2013
    Posts
    20
    Okay, I have a better grasp on just what's going on here - thanks to those responding to the question.

    As to the other discussion that started - and is informative, consider the context of this thread. You have a question from a C++ newbie who obviously knows Java (my reference to the extends keyword in Java). I also stated I'm used to Java and Perl. One thing these two languages have in common that is different in C++ is garbage collection.

    So I think it's important to take that in mind. While I used to program in 65C02 Assembler (back in the dark ages of the 1980s), I've never had to worry about memory issues in terms of remembering to delete objects.

    QT and other GUI toolkits may automatically delete their own objects, but for a newbie, the point that I need to remember to use new so it doesn't go on the stack (I've already had seg faults because I didn't know that when I was learning Crypto++), this is an important point to make.

    And I'd go so far as to say that for a newbie, I'm better off getting in the habit of making sure I destroy everything, even if it'd automatically be destroyed once it's out of scope.

    I think that, as part of the context of the discussion about who's right or wrong and who knows or doesn't know QT is more important.

  6. #21
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    Quote Originally Posted by whiteflags View Post
    Mmm, but then we come back to the fact that Qt is doing something that a lot of GUI packages do, and you are expected to read the documentation/know it well enough to understand the code. A lot of things are not necessarily self documenting (inheritence and initializer lists use the same syntax token but they have different semantics).
    Even reading the documentation does not make one an expert. It is easy to not know where to use new and where one must delete. A self documenting interface reduces this problem.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #22
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,415
    And I'd go so far as to say that for a newbie, I'm better off getting in the habit of making sure I destroy everything, even if it'd automatically be destroyed once it's out of scope.
    O_o

    I realize you are a newbie and therefore have a newbie perspective so please understand I'm only trying to enlighten.

    You are totally wrong. ^_^

    First off, if you destroy something you don't own, it will likely get destroyed twice which might very well summon "He Who Lurks Beyond The Veil" who will do awful things to your private places. In all seriousness, do not delete by any method an object you do not own.

    Now then, C++ has "RAII". (GOOGLE IT!)

    You are far better off using facilities that implement reference sharing (These would be your `shared_ptr' in C++11.), "RAII", and containers which manage elements for you.

    You want to know a secret? (This would be one of those fancy "best kept secrets".)

    Great C++ programmers basically never call `delete' and only call `new' to immediately stick it in some form of smart pointer.

    The great exception to this rule, and one you will not come across for a time, is when these programmers are creating a variety of smart pointer.

    There are a handful of less exceptions, but they are exactly that: the exception and not the rule.

    It would have been easy just to create a simple container that implicitly delegates that information, such as do_not_delete<T>.
    O_o

    The object that does the dirty work isn't relevant to the line of code where you have a problem.

    As far as we are concerned, the underlying container may be called `do_not_delete'.

    You had a problem with the self-registering nature of the contained object; specifically, you have a problem with the code because you didn't know it was self-registering because you can't tell from the code that the constructor is self-registering.

    If the "Qt" base object was named `QtDoNotDelete', you'd still have the same problem with that line of code because the base, here being `QtDoNotDelete', would still not be referenced.

    If you want to get really ugly, in concept, interface, and implementation, you could:

    Code:
    Button * s((new Button(/*???*/))->transferOwnership(this));
    Which doesn't need to use templates, is allowable in the initialize list for a class, and almost satisfies the self-documenting rule.

    It is also awful, and I honestly feel a little ill for having written that bit of code.

    However, we now have a couple of different problems.

    How do we get programmers to remember to call `transferOwnership'?

    How do we "unhook" destruction for stack objects? (This, obviously, could and should be part of `transferOwnership'.)

    How do we differentiate stack objects that have had ownership transferred? (Should we add another interface to query ownership?)

    I know! We will put the creation and registration in the same interface...

    Wait.

    Wait.

    Wait.

    $*%&YOU RECURSION!

    [Edit]
    The filter didn't do the one thing it is supposed to do.
    [/Edit]

    I use a raw pointer and attach a // DO NOT DELETE comment to ensure it's self documenting.
    o_O

    All joking aside, you have a godawful definition of self-documenting.

    Soma
    Last edited by phantomotap; 03-25-2013 at 07:05 PM.
    TangoOversway and Elkvis like this.

  8. #23
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    You know, a simple
    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    would have been just fine to self document that line of code. Obviously auto_deleter would be defined as something like
    Code:
    template<typename T> QtAutoDeleter<T> auto_deleter(T* p) { return QtAutoDeleter<T>(p); }
    And just to drive the point home, QtAutoDeleter would be defined as something like
    Code:
    template<typename T> class QtAutoDeleter
    {
    public:
    	explicit QtAutoDeleter(T* p): m_p(p) {}
    	T* get() { return m_p; }
    private:
    	T* m_p;
    }
    If you want to be paranoid, get could be private and you could friend declaratives. But that doesn't scale very well.
    Last edited by Elysia; 03-25-2013 at 07:19 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #24
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    Quote Originally Posted by Elysia View Post
    Even reading the documentation does not make one an expert.
    So? It goes a long way, no matter how you want to style yourself.

    It is easy to not know where to use new and where one must delete. A self documenting interface reduces this problem.
    PEBKAC.

  10. #25
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,415
    And just to drive the point home, QtAutoDeleter would be defined as something like
    O_o

    The functionality already works exactly as intended.

    Just to drive home the point: you are asking for decoration!

    Code:
    static inline QtBase /*whatever*/ * auto_deleter
    (
        QtBase /*whatever*/ * fParent
    )
    {
        return(fParent);
    }
    My code does what your code does, decoration, and does it better (My code would likely never exist in the binary.).

    The interesting thing about your example is the name `auto_deleter'.

    If I see `QtAutoDeleter<T> s(this);' I think that `s' is something that deletes `this'.

    You could argue that a different name, perhaps `registrar' or `GetCollection', would work.

    You could be "paranoid" and solve the problem more reasonably by having `GetCollection', or whatever, return an object that stores the container, the parent, which is friends with the container class, the `QtBase' or whatever, allowing you to prevent children from calling a `private' `registerChild' without some silly stuff. This, trivially shown, works better than your example because it doesn't need templates, a single `friend' is necessary to provide some level of protection against people not using the interface, and could be "compiled out", thanks to the above function and couple of macros, in release builds.

    If you could come up with a great name for it, I'll happily buy the interface off of you for 3 internets (no cache value). (Yes, that was a bad joke. I'm not sorry.)

    Strangely enough, it doesn't help the argument about documentation not one bit.

    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    If I didn't know about the "Qt" library strategy and your source I would immediately assume that the code was broken exactly as you did for the original.

    Not knowing that the bizarre interface above registers `edit' for deletion would have me thinking that I owned `edit' so I would be calling `delete'.

    So, 15 posts later and we are back where we started: if you don't read the documentation you're in for a world of hurt.

    Soma
    Last edited by phantomotap; 03-25-2013 at 07:55 PM.
    whiteflags likes this.

  11. #26
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    Quote Originally Posted by phantomotap View Post
    Just to drive home the point: you are asking for decoration!
    Yes, I am asking for decorations because it is an easy way to self decorate the interface.

    My code does what your code does, decoration, and does it better (My code would likely never exist in the binary.).
    Sure, but how does it decorate the interface? This can decorate the line where you call the function, but not the interface.

    The interesting thing about your example is the name `auto_deleter'.

    If I see `QtAutoDeleter<T> s(this);' I think that `s' is something that deletes `this'.
    As would I, and in this case, that is a good thing™.
    Passing off this to some function which may potentially delete it is dangerous™, and should be avoided.
    It would be much better if I could pass this to some function which would tell me it would not delete it (something like QtDoNotDelete<T>).
    It would be much safer if the function that creates the object assumes the responsibility for cleaning it up (whether that is by using some smart pointer or delegating the responsibility to some other object). That makes it less likely that it will be deleted twice.

    Strangely enough, it doesn't help the argument about documentation not one bit.

    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    If I didn't know about the "Qt" library strategy and your source I would immediately assume that the code was broken exactly as you did for the original.

    Not knowing that the bizarre interface above registers `edit' for deletion would have me thinking that I owned `edit' so I would be calling `delete'.

    So, 15 posts later and we are back where we started: if you don't read the documentation you're in for a world of hurt.
    The point is not that a programmer should ignore the documentation. That is never a good idea. The documentation should be read by anyone who attempts to use the library.
    But you are in a world of hurt even after you read the documentation until you figure out how to use the library properly and figuring out how to deal with its quirks. The idea is to guide programmers along with a self documenting interface, so they make fewer mistakes.
    And the idea is also to help out with things such as peer reviews, and with posts on forums like this. When seeing raw pointers in the code that are undecorated, many would raise concerns. And that is a valid point, since we mostly don't know what exactly those pointers are used for.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #27
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    One man's decoration is another man's noise. I think we're entering into a truly pointless argument about syntactic sugar but at some point you have to make an effort, at least until programs are capable of programming themselves. And while you say you aren't backpedaling, but we are moving backwards from your original claims. All it takes is one misunderstanding about what this communicates:
    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    And we can find ourselves right back in the argument...
    Well this isn't self documenting...
    ...Well you could read the documentation
    ...maybe there should be a comment in the source
    ....Then why did I pay that person who put together the docs pages?

    It's an infinite regress until we reach some individual's "Yeah I get it" point.
    Elkvis likes this.

  13. #28
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,014
    Quote Originally Posted by whiteflags View Post
    One man's decoration is another man's noise. I think we're entering into a truly pointless argument about syntactic sugar but at some point you have to make an effort, at least until programs are capable of programming themselves. And while you say you aren't backpedaling, but we are moving backwards from your original claims. All it takes is one misunderstanding about what this communicates:
    Of course there are going to be people who do not understand it. That's life.
    If I create some void foo(std::list), then there are going to be some people who do not understand what it is (List? What kind of list?). But to some people it will, and if you use good names, chances are a lot of people will get it. And that's good enough.

    And we can find ourselves right back in the argument...
    Well this isn't self documenting...
    ...Well you could read the documentation
    ...maybe there should be a comment in the source
    ....Then why did I pay that person who put together the docs pages?

    It's an infinite regress until we reach some individual's "Yeah I get it" point.
    Reading the documentation is always a good idea. But that's not the idea behind self documenting. We have a very article about how you should make your interfaces self documentable! SourceForge.net: Do not remove parameter names - cpwiki
    It's more about helping programmers call the interface correctly and helping them remember how to call it without consulting the documentation.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #29
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    I submit that you are now complaining to people who can do nothing to change the bad situation that you find in a library that you don't use.
    Elkvis likes this.

  15. #30
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,415
    As would I, and in this case, that is a good thing™.
    What?

    You can't be serious!?

    There isn't a font-size large enough.

    Are you being deliberately obtuse?

    Did you manage to find code online relevant to the discussion without actually reading it?

    Where did the code in your post even come from if you didn't write it?

    If you wrote it, how did you manage to so poorly understand your own code?

    Can you write code while blindfolded only with the blind covering your brain? Can you code while brainfolded?

    WTF! o_o

    You and you alone brought `QtAutoDeleter' into this discussion.

    The `QtAutoDeleter' does not delete anything. Ever.

    Code:
    QtAutoDeleter<T> s(this);
    This code implying that `QtAutoDeleter' deletes `this' is flawed.

    This code is infinitely worse than being ambiguous, confusing, unusual, or poorly documented; it self-documents as being completely unrelated to its actual purpose.

    How is this a "Good Thing™"?

    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    This code does not create an object that deletes `this'.

    This code updates a list which deletes `edit'.

    How is the names `QtAutoDeleter' and `auto_deleter' causing me to think that `this' is going to be automatically deleted "Good Thing™"?

    When seeing raw pointers in the code that are undecorated, many would raise concerns.
    O_o

    Code:
    auto edit = new QTextEdit(auto_deleter(this));
    Let me tell you something: `edit' is an undecorated pointer.

    Again: The changes to the code that you and you alone recommended decorates `this' not `edit'.

    Once more: the changes you suggested leaves the pointer to the object being registered for deletion a normal, simple, raw, dumb, undecorated, as vanilla as you please pointer.

    Seriously, you just skewed your own suggestion to such a perverse shape not even Cthulhu could make it out without its eyes watering.

    The beast that dwells in a non-euclidean space is looking at this thread scratching its head because you've just told us that the code that self-documents as doing something completely unrelated to its actual purpose is superior to the code that you find "insane" only because it isn't self-documenting.

    I can't help but think that this was a wonderful troll, and in that spirit, I have to say: well done!

    Wow.

    Really.

    Well played; I'm grinning like the Cheshire Cat on copious quantities of the nip.

    Soma
    whiteflags likes this.

Page 2 of 3 FirstFirst 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 12-17-2011, 06:15 PM
  2. newbie question: how to start ubuntu?
    By Yarin in forum Tech Board
    Replies: 11
    Last Post: 08-14-2008, 06:59 PM
  3. Compiler Syntax Error (Newbie Question)
    By NewCProgrammer in forum C Programming
    Replies: 8
    Last Post: 04-22-2008, 08:45 AM
  4. Replies: 3
    Last Post: 10-31-2006, 02:15 AM
  5. newbie wonders how to start c++
    By buraks78 in forum C++ Programming
    Replies: 3
    Last Post: 06-18-2003, 10:54 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21