5b35552d   
   From: daniel.kruegler@googlemail.com   
      
   Am 22.11.2011 20:44, schrieb Andrzej Krzemieński:   
   > I am trying to implement a template "wrapper" for any arbitrary type,   
   > much like boost::optional. In fact I am trying to write my own   
   > alternative implementation of optional. I want it to have the   
   > following property: if the wrapped type T ptovides copy constructor,   
   > optional also provides a copy constructor; similarly, optional   
   > provides a move constructor iff T provides one. With concepts (as   
   > defined in N2914), I would express it like this:   
   >   
   > template< typename T>   
   > struct Optional   
   > {   
   > requires CopyConstructible   
   > Optional( Optional const& );   
   >   
   > requires MoveConstructible   
   > Optional( Optional&& );   
   > };   
      
   Note that even with concepts these constrained member functions would   
   not have changed the actual copy-constructor into a "constrained special   
   member function", see 9.2 p19:   
      
   "A constrained member is treated as a constrained template (14.11)   
   whose template requirements include the requirements specified in its   
   member-requirement clause and the requirements of each enclosing   
   constrained template."   
      
   This has the effect that 12.8, especially footnote 113:   
      
   "Because a template constructor or a constructor whose first parameter   
   is an rvalue reference is never a copy constructor, the presence of such   
   a constructor does not suppress the implicit declaration of a copy   
   constructor. Such constructors participate in overload resolution with   
   other constructors, including copy constructors, and, if selected, will   
   be used to copy an object."   
      
   was still in effect and thus would not have prevented the copy/move   
   constructor to be declared.   
      
   > Do you know of any way to implement similar behavior in C++11? The   
   > enable_if trick does not seem to work for disabling the default   
   > constructor.   
      
   I assume here, that instead of the "default constructor" you actually   
   mean the "implicitly-declared copy/move constructor" (otherwise I   
   wouldn't understand your previous comment about constrained member   
   functions).   
      
   If I correctly understand you, Optional does not contain a member or   
   base of type T (otherwise the compiler-declared constructors would   
   already work as intended), instead you have some opaque buffer for the   
   to be constructed T. In this case, I suggest the following approach   
   (ignoring the copy/move assignment operations for the moment):   
      
   Invent the following empty types:   
      
   struct copy_move1 {};   
   struct copy_move2 {};   
      
   struct move_no_copy {   
    move_no_copy(const move_no_copy&) = delete;   
    move_no_copy(move_no_copy&&) = default;   
   };   
      
   struct copy_no_move {   
    copy_no_move(const copy_no_move&) = default;   
    copy_no_move(copy_no_move&&) = delete;   
   };   
      
   Define a so-called TransformationTrait (see 20.9.1), name it copy_base,   
   that has a single template parameter T and that defines a member type   
   "type" such that   
      
   if std::is_copy_constructible::value == true then type is equal to   
   copy_move1, else type is equal to move_no_copy.   
      
   This can easily be realized via std::conditional:   
      
   template   
   struct copy_base : std::conditional<   
    std::is_copy_constructible::value,   
    copy_move1, move_no_copy>   
   {};   
      
   Define a second TransformationTrait, name it move_base, that has a   
   single template parameter T and that defines a member type "type" such that   
      
   if std::is_move_constructible::value == true then type is equal to   
   copy_move2, else type is equal to copy_no_move.   
      
   Once you have done so, you start defining Optional like so:   
      
   template< typename T >   
   struct Optional : private copy_base::type,   
    private move_base::type   
   {   
   };   
      
   The effects should be as if you had a member (or base class) that has   
   the same copy/move behaviour as T.   
      
   Does this answer your question?   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|