home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 33,211 of 33,346   
   Kamil Rojewski to All   
   Re: Template setters (1/2)   
   18 Sep 13 13:10:29   
   
   From: kamil.rojewski@googlemail.com   
      
   > The "setter's designer" /must/ know design details of class she designs   
   > and certainly the type of particular attribute of class that particular   
   > method modifies. Also she should know the types of arguments that are   
   > passed to all interface of the class. If part of the interface is template   
   > then it should verify that the concepts match. How else? Does she deserve   
   > to be freed of that knowledge?   
      
   I think you mistakenly assumed I was talking about about knowing the   
   class the setter is in. Correct me if I'm wrong on this. To clarify -   
   I meant the type of the variable member being set. The only knowledge   
   required is the knowledge of the availability of operator =, which is   
   also the case in "traditional" setters. Let's bring back the example:   
      
       template   
       void setWidget(T &&widget)   
       {   
            mWidget = std::forward(widget);   
       }   
      
   As you can see, there is not a single type specification anywhere.   
   The setter only assumes some overload of operator = exists (not   
   exactly true strictly speaking, because when the setter is not used,   
   there is no need for operator = to exist and compilation goes on just   
   fine, but that's a case when the setter shouldn't exist in such form   
   in the first place). The setter designer is indeed freed from any   
   knowledge of the type of mWidget, especially what overloads of its   
   operator = exist. Note, that if mWidget is a template type itself,   
   such setter is pretty much the only way to provide generic setting   
   mechanism. That alone implies this kind of setter is as type agnostic   
   as it can be.   
      
   > The "setter's user" should know the types of arguments that may be   
   > passed to the part of interface she uses. She may not know the types   
   > used internally in class ... that is called "encapsulation". That is   
   > broken since the interface depends on overloads of 'operator=' and   
   > the errors about those are the only indication of types of expected   
   > arguments to your setters.   
      
   You have a point there, but I think only partially. The setter alone   
   /could/ require the knowledge of the type of the member being set.   
   But that knowledge is usually already passed to the user in the form   
   of associated getter return type, documentation, etc. If such   
   knowledge is not available, template setter can indeed be a bad idea.   
      
   > That logic leaves impression that you try to free class designers   
   > from knowing (and caring about) the types of components of class?   
      
   By all means, no. The setter is only one use case of a member. Your   
   implication would be true if there was noting more using that member,   
   than the setter or equivalent. And we do have such situations - STL   
   containers, for one example. They have the equivalents in the form of   
   emplace() functions. You can try to extend it onto whole  family of   
   classes containing templated members, only relying on the type   
   properties, as concepts tend to provide.   
      
   > Again: "setter" will be decoupled from type it sets? What is the   
   > benefit?   
      
   Taking into account every available operator = overload, without code   
   duplication; including modern language features like move semantics.   
   Also being future-proof.   
      
   > IOW if I needed what you wrote then I would write it like that:   
   >   
   >    void copyToTheX( XPtr const& x )   
   >    {   
   >        theX.reset( x ? new X(*x) : nullptr );   
   >    }   
   >   
   >    void moveToTheX( XPtr&& x )   
   >    {   
   >        theX = x;   
   >    }   
      
   That is a valid approach, but very limiting. What if someone wants   
   to set nullptr to theX? Which one should he use? None logically seems   
   appropriate. Would you write another function, setTheX/setTheXPointer   
   or similar? What if you wanted to take advantage of other possible   
   operator = overloads (let's assume there are some)? More functions,   
   with possibly more code duplication? When all pretty much logically   
   /set/ theX to the parameter. One template setter does all that. (I   
   also assumed you meant using std::move() in moveToTheX(), because now   
   it's trying to make a copy).   
      
   > Variable /was/ set to new value and it was not copied anywhere.   
   > Argument was not moved but ... so what? It was not damaged in any way.   
      
   Variable was indeed set to the new value, but with two dangerous   
   assumptions:   
      
   1. The underlying type X is copyable and the possible side effects of   
      making such copy are not dangerous or otherwise undesired.   
   2. The original value is safe to be freed, with possible side effects   
      also not being dangerous or otherwise undesired. Additional   
      assumption is that the original pointer is not stored anywhere in   
      raw form.   
      
   > Then why not to enforce it with 'T&&' parameter?   
      
   If you meant unique_ptr&& here, you could enforce it, but the   
   problems with not utilizing other possible operator = overloads and   
   being future-proof still remain.   
      
   > I do not use such /assumptions/ whatsoever. X was clearly /declared/   
   > copyable in my code. For interface maker it /must/ be clear.   
      
   Yes it was clearly declared copyable. But when writing the setter you   
   /have to/ check it and tie yourself to what you see there in that   
   very moment. Why then not write it in a generic way and be certain   
   your code will work, regardless of X? The only way it will produce a   
   compile error is when a user misuses it. But the knowledge of the   
   type the user uses is natural.   
      
   > You did bring 'unique_ptr' as example of movable but not copyable   
   > type yourself?   
      
   Yes, to show how that coupling with the type works, hence my reply.   
      
   > I do not expose what I internally use, ever. If the class uses   
   > internally 'auto_ptr' or raw pointer (for whatever legacy reasons)   
   > or 'shared_ptr' (since my side of interface actually uses it in   
   > shared way) then I may still use move-only interface with   
   > 'unique_ptr'. The concerns of implementer of class and user of class   
   > should be separated.   
      
   That means you are keeping legacy interface. That is valid as long as   
   it is possible. I'm not disputing keeping the interface invariant as   
   this is a good practice. I'm suggesting that this might not be   
   possible and might become logically awkward.   
      
   > I repeat you did bring 'unique_ptr' as example of movable but not   
   > copyable type yourself? It was example as reply to that. If you need   
   > example about something else then ask away.   
      
   The example was good, since it presents a situation, which introduces   
   potential problems. Solving problematic situations can show the   
   validity (or not) of the idea being presented.   
      
   > How often you need to switch between 'shared_ptr' and 'unique_ptr' as   
   > internal design detail? For me those types were exactly made to get rid   
   > of loose concept of C pointer. Raw pointer sometimes means   
   > 'unique_ptr' for single element, sometimes 'unique_ptr' for possibly   
   > several elements, sometimes 'shared_ptr', sometimes 'weak_ptr',   
   > sometimes 'vector' and sometimes 'iterator' and so on. However the   
      
   [continued in next message]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca