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,201 of 33,346   
   =?ISO-8859-1?Q?=D6=F6_Tiib?= to Kamil Rojewski   
   Re: Template setters (1/2)   
   10 Sep 13 22:14:49   
   
   From: ootiib@hot.ee   
      
   On Tuesday, 10 September 2013 10:50:02 UTC+3, Kamil Rojewski  wrote:   
   > > Lets see your setter: First type falls aside (it has both 'operator='   
   > > deleted, but it may be is cloned in setter). It also feels   
   > > needless complication to have such template for next two kinds since   
   > > one can use only 'T const&' and other only 'T&&'. So only the last   
   > > kind (that has both 'operator='s intact) can benefit from the template.   
   >   
   > You are right on this one. When a type is only copyable or only   
   > movable, this approach seems unnecessary. But then we are relying on   
   > the knowledge of that type, while making a function contained in   
   > another class. What if the type suddenly became copyable/movable?   
      
   That is the logical problem that I try to bring your attention at.   
   Most types that lack some ability should lack it. The reason is   
   conceptual nature of type. Some things (like thread, file descriptor)   
   are not copyable. Others (like some atomic) are not movable. Numerous   
   things (most dynamically polymorphic objects) are neither. That is   
   because of the very nature of the objects and not because of strange   
   whim of designers.   
      
   > Using a template would ensure future-correctness in a type-agnostic   
   > way. It could be viewed as a form of extensibility (not much, but   
   > still) and reducing coupling. In this case, the question boils down to   
   > assessing if such approach has merit for a given type. If we take into   
   > account the last example with both copy and move, we could end up with   
   > templated and non-templated versions, based on this assessment. I   
   > think it warrants further analysis.   
      
   It is needless complication added to code if it anticipates that   
   something that is highly unlikely (a thread becomes copyable) may   
   happen. C++ is strongly typed. Interfaces dictate types, generic   
   interfaces dictate conceptual nature of types (with traits and   
   'enable_if's). "Anything goes" is not good policy for C++.   
      
   > > Lets see old way: We can easily have 'T const&' for each kind. That   
   > > makes 'T const&' lot better candidate for uniformity.   
   >   
   > Yes and no. It doesn't work for non-copyable, but movable types   
   > (unique_ptr for example).   
      
   Maybe 'unique_ptr' is bad example since it is usually conceptually   
   not attribute itself but merely a "unique reference" to actual   
   attribute. I trust it must work with 'T const&'. Anything must.   
   Does not below code work? (I haven't tested myself but it feels   
   it should):   
      
      #include    
      struct X {};   
      
      typedef std::unique_ptr XPtr;   
      
      XPtr theX;   
      
      void setTheX( XPtr const& x )   
      {   
          theX.reset( x ? new X(*x) : nullptr );   
      }   
      
      int main()   
      {   
          XPtr someX( new X );   
          setTheX( someX );   
          XPtr noX;   
          setTheX( noX );   
      }   
      
   > For everything else, it's sufficient. But   
   > it doesn't benefit from move semantics and logical implicit   
   > conversions by the use of operator = overloading, like   
   > operator =(nullptr_t) in unique_ptr.   
      
   I do not suggest to use 'T const&' as uniform way to pass parameters.   
   I merely pointed out that it is better candidate for such uniformity.   
   For me it is fine when conceptually different parameters are passed   
   differently and that the interfaces make it clear.   
      
   > > Side question: Why exactly only the "setters" for that kind? /Any/   
   > > function in what copying or assignment of parameter is made /may/   
   > > benefit from that trick.   
   >   
   > Setters are explicitly designed to set and only set a field in a class   
   > to the value supplied by the parameter. Using this trick on other   
   > methods, exposes their inner workings and breaks encapsulation.   
      
   How? You turn something in interface into generic (template) and that   
   somehow exposes something and breaks encapsulation? For me it loosens   
   interface (might be overly so designer likely has to add trait checks)   
   and does not expose nor break anything.   
      
   > Even more - it makes them constrained (quite ironic), since they   
   > would /have to/ always allow different types as input, while the   
   > implementation might change in a way that only one concrete type is   
   > supported, thus not being able to enforce type-correctness.   
      
   Oh. Template in interface does not mean that "anything goes"?   
   I just asked why /only/ setters. I myself use that trick /only/ when:   
    0) the type is movable and copyable /and/   
    1) it is clear that move will help (for example profiling shows) /and/   
    2) the bodies of move and copy overloads would be exactly same /and/   
    3) I do not want to burden callers with always making movables for   
       move-only version of interface.   
   That reads "rarely".   
      
   > After all, we code against interfaces, not implementations.   
      
   That is true and that is why I dislike "setters". Too exposing and   
   intrusive (forces users to deal with other classes internal details)   
   interface for my taste.   
      
   > > Had the problem been in template I would just suggest two overloads   
   > > like 'operator=' has. The problem is that it will logically complicate   
   > > things because the nature of different IN parameters is different.   
   > > Removing that difference means making most types moveable and copyable   
   > > and that feels wrong (about as wrong as making most member functions   
   > > virtual).   
   >   
   > I disagree on the part about "making" a type moveable and copyable.   
   > The type is left alone; there is no need of any knowledge about it at   
   > the setter level.  This approach is completely safe in this regard as   
   > no knowledge about the type is assumed.   
      
   Here I am confused. Lets see:   
      
     template   
     void setWidget(T &&widget) // <- until here too few knowledge.   
     {   
         mWidget = std::forward(widget); // <- errors here about no   
                                            //    suitable 'operator='   
                                            //    for internal design   
                                            //    detail. Too much   
                                            //    knowledge required.   
     }   
      
   The user of interface needs not only know types that can be passed in   
   but what the heck is that 'mWidget' and what set of 'operator=' its   
   type has. How it is "there is no need of any knowledge about it"?   
      
   > Making two overloads requires the type to be able to accept the two   
   > different input parameters we incorporate in the setters.   
   > That type would be constrained by our   
   > setters and our class would also be constrained by the type. Removing   
   > the ability to be copied or moved would break every line that uses   
   > such functionality explicitly, but would also break every line that   
   > uses our setters. And if the type would suddenly get copyable or   
      
   [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