How to Overload the Operator '->' (ptr to member access) and Build a Smart Pointer in FB

Forum for discussion about the documentation project.
fxm
Posts: 9021
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

How to Overload the Operator '->' (ptr to member access) and Build a Smart Pointer in FB

Postby fxm » Jul 15, 2014 19:35

1) Overloading operator '->' (pointer to member access)
    The operator '->' (pointer to member access) is used to access any member of an object (instance) via a pointer to this instance.
    Under normal circumstances, the left operand of this operator must be a pointer to an object instance:

    Code: Select all

    Declare Operator -> ( ByRef lhs As T Ptr ) ByRef As U

    Overloading of this operator allows you to create a pointer wrapper class and let it behave like the pointer itself:

    Code: Select all

    Declare Operator -> ( ByRef lhs As wrapperClass ) [ByRef] As U
      The wrapper can be then used (to access a member) like:
      wrapper->member
      instead of:
      wrapper.realPointer->member
    Clarifying the particular case of overloading the operator '->' (pointer to member access):
    • The operator '->' exhibits a different behavior from the other operators with respect to overloading:
        - It doesn't return only the user datatype as indicated in the overloaded procedure header,
        - but it returns this user datatype implicitly followed by the operator '.' (member access).
        (the operator '.' (member access) cannot be overloaded itself)
    • The operator '->' is mainly used often in conjunction with the operator '*' to implement the "smart pointers".
2) Using smart pointer
    The use of smart pointers allows automatic management of dynamic references created by New (each reference is destroyed automatically when its smart pointer goes out of scope), without even making any copy of these references.

    Reminder of what a smart pointer:
    • A smart pointer is an object which behaves like a pointer but does more than a pointer.
    • This object is flexible as a pointer and has the advantage of being an object (like constructor and destructor called automatically).
    • Therefore, the destructor of the smart pointer will be automatically called when this object goes out of scope, and it will delete the user pointer.
    As the smart pointer must behave like a pointer, it must support the same interface as a pointer does.
    So it must support the following operations:
    • Dereferencing (operator '*')
    • Indirection (operator '->')
    These two operators ('*' and '->') must return references (by means of using 'Byref As .....' in the declaration of there return type).

  • Example of an elementary smart pointer (to UDT) with a minimum interface:
    - default-constructor
    - destructor
    - operator '->'

    Code: Select all

    Type UDT
      Declare Constructor ()
      Declare Destructor ()
      Dim As String s = "object #0"
    End Type

    Constructor UDT ()
      Print "  UDT construction "; @This
    End Constructor

    Destructor UDT ()
      Print "  UDT destruction "; @This
    End destructor

    Type SmartPointer
      Declare Constructor ()                            '' to construct smart pointer (and UDT object)
      Declare Destructor ()                             '' to destroy smart pointer (and UDT object)
      Dim As UDT Ptr p                                  '' UDT pointer
    End Type

    Constructor SmartPointer ()
      Print "SmartPointer construction "; @This
      This.p = New UDT
    End Constructor

    Destructor SmartPointer ()
      Print "SmartPointer destruction "; @This
      Delete This.p
    End destructor

    Operator -> (Byref sp As SmartPointer) Byref As UDT  '' overloaded operator '->'
      Print "SmartPointer operator '->'"
      Return *sp.p                                       ''    (returning byref)
    End Operator                                         ''    to behave as pointer
     

    Scope
      Dim sp1 As SmartPointer
      Print "'" & sp1->s & "'"
      sp1->s = "object #1"
      Print "'" & sp1->s & "'"
      Print
    End Scope

    Sleep

    Code: Select all

    SmartPointer construction 1703592
      UDT construction 10168960
    SmartPointer operator '->'
    'object #0'
    SmartPointer operator '->'
    SmartPointer operator '->'
    'object #1'

    SmartPointer destruction 1703592
      UDT destruction 10168960

  • Example of an improved smart pointer (to UDT) with an improved interface:
    - public default-constructor
    - public copy-constructor
    - public destructor
    - private UDT pointer and public operator 'cast' to access it in read only mode
    - private operator 'let' to disallow assignment (to avoid copy of real pointers)
    - operator '*' and operator '->'

    Code: Select all

    Type UDT
      Declare Constructor ()
      Declare Destructor ()
      Dim As String s = "object #0"
    End Type

    Constructor UDT ()
      Print "  UDT construction "; @This
    End Constructor

    Destructor UDT ()
      Print "  UDT destruction "; @This
    End destructor

    Type SmartPointer
      Public:
        Declare Constructor ()                            '' to construct smart pointer (and UDT object)
        Declare Constructor (Byref rhs As SmartPointer)   '' to copy construct smart pointer
        Declare Operator Cast () As UDT Ptr               '' to cast private UDT pointer (for read only)
        Declare Destructor ()                             '' to destroy smart pointer (and UDT object)
      Private:
        Dim As UDT Ptr p                                  '' private UDT pointer
        Declare Operator Let (Byref rhs As SmartPointer)  '' to disallow assignment (to avoid copy of real pointers)
    End Type

    Constructor SmartPointer ()
      Print "SmartPointer construction "; @This
      This.p = New UDT
    End Constructor

    Constructor SmartPointer (Byref rhs As SmartPointer)
      Print "SmartPointer copy-construction "; @This; " from "; @@rhs
      This.p = New UDT
      *This.p = *rhs.p
    End Constructor

    Operator SmartPointer.Cast () As UDT Ptr
      Print "SmartPointer operator 'cast'"
      Return This.p
    End Operator

    Destructor SmartPointer ()
      Print "SmartPointer destruction "; @This
      Delete This.p
    End destructor

    Operator * (Byref sp As SmartPointer) Byref As UDT   '' overloaded operator '*'
      Print "SmartPointer operator '*'"
      Return *Cast(UDT Ptr, sp)                          ''    (returning byref)
    End Operator                                         ''    to behave as pointer
     
    Operator -> (Byref sp As SmartPointer) Byref As UDT  '' overloaded operator '->'
      Print "SmartPointer operator '->'"
      Return *Cast(UDT Ptr, sp)                          ''    (returning byref)
    End Operator                                         ''    to behave as pointer
     

    Scope
      Dim sp1 As SmartPointer
      Print "'" & sp1->s & "'"
      sp1->s = "object #1"
      Print "'" & sp1->s & "'"
      Print
     
      Dim sp2 As SmartPointer = sp1
      Print "'" & (*sp2).s & "'"
      (*sp2).s = "object #2"
      Print "'" & (*sp2).s & "'"
      Print
     
      Dim sp3 As SmartPointer = sp1
      Print "'" & sp3->s & "'"
      *sp3 = *sp2
      Print "'" & sp3->s & "'"
      sp3->s = "object #3"
      Print "'" & sp3->s & "'"
      Print
    End Scope

    Sleep

    Code: Select all

    SmartPointer construction 1703592
      UDT construction 5974656
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    'object #0'
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    'object #1'

    SmartPointer copy-construction 1703540 from 1703392
      UDT construction 5974728
    SmartPointer operator '*'
    SmartPointer operator 'cast'
    'object #1'
    SmartPointer operator '*'
    SmartPointer operator 'cast'
    SmartPointer operator '*'
    SmartPointer operator 'cast'
    'object #2'

    SmartPointer copy-construction 1703488 from 1703392
      UDT construction 5974800
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    'object #1'
    SmartPointer operator '*'
    SmartPointer operator 'cast'
    SmartPointer operator '*'
    SmartPointer operator 'cast'
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    'object #2'
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    SmartPointer operator '->'
    SmartPointer operator 'cast'
    'object #3'

    SmartPointer destruction 1703488
      UDT destruction 5974800
    SmartPointer destruction 1703540
      UDT destruction 5974728
    SmartPointer destruction 1703592
      UDT destruction 5974656

  • Example of an extended smart pointer type macro for any UDT, with an extended interface:
    - public constructor
    - public reference counter in read only mode
    - public destructor
    - private UDT pointer and 2 public operators 'cast' to access it in read only mode (numeric value and string value)
    - private default-constructor to disallow self construction
    - private copy-constructor to disallow cloning
    - private operator 'let' to disallow assignment
    - operator '*' and operator '->'

    Code: Select all

    #Macro Define_SmartPointer (_UDTname_)

      Type SmartPointer_##_UDTname_
        Public:
          Declare Constructor (Byval rhs As _UDTname_ Ptr)              '' to construct smart pointer
          '                                                                '' from _UDTname_ pointer,
          '                                                                '' with reference counter increment
          Declare Static Function returnCount () As Integer             '' to return reference counter value
          Declare Operator Cast () As _UDTname_ Ptr                     '' to cast private _UDTname_ pointer
          '                                                                '' to _UDTname_ pointer (read only)
          Declare Operator Cast () As String                            '' to cast private _UDTname_ pointer
          '                                                                '' to string (read only)
          Declare Destructor ()                                         '' to destroy smart pointer
          '                                                                '' and _UDTname_ object
          '                                                                '' with reference counter decrement
        Private:
          Dim As _UDTname_ Ptr p                                        '' private _UDTname_ pointer
          Static As Integer Count                                       '' private reference counter
          Declare Constructor ()                                        '' to disallow default-construction
          Declare Constructor (Byref rhs As SmartPointer_##_UDTname_)   '' to disallow copy-construction
          Declare Operator Let (Byref rhs As SmartPointer_##_UDTname_)  '' to disallow copy-assignment
      End Type
      Dim As Integer SmartPointer_##_UDTname_.Count = 0

      Constructor SmartPointer_##_UDTname_ (Byval rhs As _UDTname_ Ptr)
        If rhs <> 0 Then
          This.p = rhs
          SmartPointer_##_UDTname_.count += 1
        End If
      End Constructor

      Static Function SmartPointer_##_UDTname_.returnCount () As Integer
        Return SmartPointer_##_UDTname_.count
      End Function

      Operator SmartPointer_##_UDTname_.Cast () As _UDTname_ Ptr
        Return This.p
      End Operator

      Operator SmartPointer_##_UDTname_.Cast () As String
        Return Str(This.p)
      End Operator

      Destructor SmartPointer_##_UDTname_ ()
        If This.p <> 0 Then
          Delete This.p
          SmartPointer_##_UDTname_.count -= 1
          This.p = 0
        End If
      End destructor

      Operator * (Byref sp As SmartPointer_##_UDTname_) Byref As _UDTname_  '' operator '*' (return byref)
        '                                                                      '' to behave as pointer
        Return Byval sp                                                     '' 'Return *sp' would induce an infinite loop
      End Operator

      Operator -> (Byref sp As SmartPointer_##_UDTname_) Byref As _UDTname_  '' operator '->' (return byref)
        '                                                                       '' to behave as pointer
        Return Byval sp
      End Operator

    #Endmacro

    '--------------------------------------------------------------------------------------------------------

    ' Example using all eight keywords of inheritance:
    '   'Extends', 'Base.', 'Base()', 'Object', 'Is' operator, 'Virtual', 'Abstract', 'Override'

    Type root Extends Object ' 'Extends' to activate RTTI by inheritance of predefined Object type
      Public:
        Declare Function ObjectHierarchy () As String
        Declare Function ObjectName () As String
        Declare Abstract Function ObjectRealType () As String  '' 'Abstract' declares function without local body
        '                                                         '' which must be overridden
        Declare Virtual Destructor ()                          '' 'Virtual' declares destructor
      Protected:
        Declare Constructor ()                                 '' to avoid default-construction from outside Types
        Declare Constructor (Byref _name As String = "")       '' to avoid construction from outside Types
        Declare Constructor (Byref rhs As root)                '' to avoid copy-construction from outside Types
        Declare Operator Let (Byref rhs As root)               '' to avoid copy-assignment from outside Types
      Private:
        Dim name As String
    End Type                                                   '' derived type may be member data empty

    Constructor root ()  '' only to avoid compile error (due to inheritance)
    End Constructor

    Constructor root (Byref _name As String = "")              '' only to avoid compile error (due to inheritance)
      This.name = _name
      Print "root constructor:", This.name
    End Constructor

    Function root.ObjectHierarchy () As String
      Return "Object(forRTTI) <- root"
    End Function

    Function root.ObjectName () As String
      Return This.name
    End Function

    Virtual Destructor root ()
      Print "root destructor:", This.name
    End Destructor

    Operator root.Let (Byref rhs As root)                      '' only to avoid compile error (due to onheritance)
    End Operator


    Type animal Extends root                                         '' 'Extends' to inherit of root
      Declare Constructor (Byref _name As String = "")
      Declare Function ObjectHierarchy () As String
      Declare Virtual Function ObjectRealType () As String Override  '' 'Virtual' declares function with local
      '                                                              ''    body which can be overridden
      '                                                              '' 'Override' to check if the function is
      '                                                              ''    well an override
      Declare virtual Destructor () Override                         '' 'Virtual' declares destructor with local body
      '                                                              '' 'Override' to check if the destructor is well an override
    End Type

    Constructor animal (Byref _name As String = "")
      Base(_name)                                                    '' 'Base()' allows to call parent constructor
      Print "  animal constructor:", This.ObjectName()
    End Constructor

    Function animal.ObjectHierarchy () As String
      Return Base.ObjectHierarchy & " <- animal"                     '' 'Base.' allows to access to parent member function
    End Function

    Virtual Function animal.ObjectRealType () As String
      Return "animal"
    End Function

    Virtual Destructor animal ()
      Print "  animal destructor:", This.ObjectName()
    End Destructor


    Type dog Extends animal                                  '' 'Extends' to inherit of animal
      Declare Constructor (Byref _name As String = "")
      Declare Function ObjectHierarchy () As String
      Declare Function ObjectRealType () As String Override  '' 'Override' to check if the function is well an
      '                                                      ''    override
      Declare Destructor () Override                         '' 'Override' to check if the destructor is well an override
    End Type                                                 '' derived type may be member data empty

    Constructor dog (Byref _name As String = "")
      Base(_name)                                            '' 'Base()' allows to call parent constructor
      Print "    dog constructor:", This.ObjectName()
    End Constructor

    Function dog.ObjectHierarchy () As String
      Return Base.ObjectHierarchy & " <- dog"                '' 'Base.' allows to access to parent member function
    End Function

    Function dog.ObjectRealType () As String
      Return "dog"
    End Function

    Destructor dog ()
      Print "    dog destructor:", This.ObjectName()
    End Destructor


    Type cat Extends animal                                  '' 'Extends' to inherit of animal
      Declare Constructor (Byref _name As String = "")
      Declare Function ObjectHierarchy () As String
      Declare Function ObjectRealType () As String Override  '' 'Override' to check if the function is well an
                                                             ''    override
      Declare Destructor () Override                         '' 'Override' to check if the destructor is well an override
    End Type                                                 '' derived type may be member data empty

    Constructor cat (Byref _name As String = "")
      Base(_name)                                            '' 'Base()' allows to call parent constructor
      Print "    cat constructor:", This.ObjectName()
    End Constructor

    Function cat.ObjectHierarchy () As String
      Return Base.ObjectHierarchy & " <- cat"                '' 'Base.' allows to access to parent member function
    End Function

    Function cat.ObjectRealType () As String
      Return "cat"
    End Function

    Destructor cat ()
      Print "    cat destructor:", This.ObjectName()
    End Destructor


    Sub PrintInfo (Byval p As root Ptr)                                     '' parameter is a 'root Ptr' or compatible (smart pointer)
      Print "  " & p->ObjectName, "  " & p->ObjectRealType, "           ";
      If *p Is dog Then                                                     '' 'Is' allows to check compatibility with type symbol
        Print  Cast(dog Ptr, p)->ObjectHierarchy
      Elseif *p Is cat Then                                                 '' 'Is' allows to check compatibility with type symbol
        Print Cast(cat Ptr, p)->ObjectHierarchy
      Elseif *p Is animal Then                                              '' 'Is' allows to check compatibility with type symbol
        Print Cast(animal Ptr, p)->ObjectHierarchy
      End If
    End Sub


    Define_SmartPointer(root)  '' smart pointer definition

    Scope
      Print "reference counter value:"; SmartPointer_root.returnCount()
      Print
      Dim As SmartPointer_root sp(2) = {New animal("Mouse"), New dog("Buddy"), New cat("Tiger")}
      Print
      Print "reference counter value:"; SmartPointer_root.returnCount()
      For I As Integer = 0 To 2
        Print "  " & sp(I), sp(I)->ObjectName()
      Next I
      Print
      Print "Name:", "Object (real):         Hierarchy:"
      For I As Integer = 0 To 2
        PrintInfo(sp(I))
      Next I
      Print
    End Scope
    Print
    Print "reference counter value:"; SmartPointer_root.returnCount()
    Print

    Sleep

    Code: Select all

    reference counter value: 0

    root constructor:           Mouse
      animal constructor:       Mouse
    root constructor:           Buddy
      animal constructor:       Buddy
        dog constructor:        Buddy
    root constructor:           Tiger
      animal constructor:       Tiger
        cat constructor:        Tiger

    reference counter value: 3
      9448064     Mouse
      9448184     Buddy
      9448304     Tiger

    Name:         Object (real):         Hierarchy:
      Mouse         animal                 Object(forRTTI) <- root <- animal
      Buddy         dog                    Object(forRTTI) <- root <- animal <- dog
      Tiger         cat                    Object(forRTTI) <- root <- animal <- cat

        cat destructor:         Tiger
      animal destructor:        Tiger
    root destructor:            Tiger
        dog destructor:         Buddy
      animal destructor:        Buddy
    root destructor:            Buddy
      animal destructor:        Mouse
    root destructor:            Mouse

    reference counter value: 0

Return to “Documentation”

Who is online

Users browsing this forum: srvaldez and 1 guest