{{fbdoc item="title" value="OPERATOR"}}----
Declares or defines an overloaded operator.

{{fbdoc item="syntax"}}##
	{ [[KeyPgType Type]] | [[KeyPgClass Class]] | [[KeyPgUnion Union]] | [[KeyPgEnum Enum]] } //typename//
		[[KeyPgDeclare declare]] **Operator** [[KeyPgCast cast]] () [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]]
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpAt @]] () [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]] [[KeyPgPtr ptr]]
		[[KeyPgDeclare declare]] **Operator** //assignment_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] )
		[[KeyPgDeclare declare]] **Operator** {{fbdoc item="keyword" value="KeyPgOpPtrIndex|[]"}} ( //index// [[KeyPgAs as]] [[DataType datatype]] ) [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]]
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpNew new]] ( //size// [[KeyPgAs as]] [[KeyPgUinteger uinteger]] ) [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]]
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpNew new]][] ( //size// [[KeyPgAs as]] [[KeyPgUinteger uinteger]] ) [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]]
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpDelete delete]] ( //buf//  [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] )
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpDelete delete]][] ( //buf//  [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] )
	End { [[KeyPgType Type]] | [[KeyPgClass Class]] | [[KeyPgUnion Union]] | [[KeyPgEnum Enum]] }

	{ [[KeyPgType Type]] | [[KeyPgClass Class]] | [[KeyPgUnion Union]] } //typename//
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpFor For]] ()
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpFor For]] ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //stp// [[KeyPgAs as]] //typename// )
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpStep Step]] ()
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpStep Step]] ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //stp// [[KeyPgAs as]] //typename// )
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpNext Next]] ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //cond// [[KeyPgAs as]] //typename// ) [[KeyPgAs as]] [[KeyPgInteger Integer]]
		[[KeyPgDeclare declare]] **Operator** [[KeyPgOpNext Next]] ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //cond// [[KeyPgAs as]] //typename//, [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //stp// [[KeyPgAs as]] //typename// ) [[KeyPgAs as]] [[KeyPgInteger Integer]]
	End { [[KeyPgType Type]] | [[KeyPgClass Class]] | [[KeyPgUnion Union]] }

	[[KeyPgDeclare declare]] **Operator** //unary_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] ) [[KeyPgAs as]] [[DataType datatype]]
	[[KeyPgDeclare declare]] **Operator** //binary_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //lhs// [[KeyPgAs as]] [[DataType datatype]], [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] ) [[KeyPgAs as]] [[DataType datatype]]

	**Operator** //typename//.[[KeyPgCast cast]] () [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]] [ [[KeyPgExport Export]] ]
	**Operator** //typename//.[[KeyPgOpAt @]] () [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]] [[KeyPgPtr ptr]] [ [[KeyPgExport Export]] ]
	**Operator** //typename//.//assignment_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] ) [ [[KeyPgExport Export]] ]
	**Operator** {{fbdoc item="keyword" value="KeyPgOpPtrIndex|[]"}} ( //index// [[KeyPgAs as]] [[DataType datatype]] ) [ [[KeyPgByrefFunction byref]] ] [[KeyPgAs as]] [[DataType datatype]] [ [[KeyPgExport Export]] ]
	**Operator** //unary_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] ) [[KeyPgAs as]] [[DataType datatype]] [ [[KeyPgExport Export]] ]
	**Operator** //binary_op// ( [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //lhs// [[KeyPgAs as]] [[DataType datatype]], [ [[KeyPgByref byref]] | [[KeyPgByval byval]] ] //rhs// [[KeyPgAs as]] [[DataType datatype]] ) [[KeyPgAs as]] [[DataType datatype]] [ [[KeyPgExport Export]] ]
	**Operator** //typename//.[[KeyPgOpNew new]] ( //size// as uinteger ) [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] [ [[KeyPgExport Export]] ]
	**Operator** //typename//.[[KeyPgOpNew new]][] ( //size// [[KeyPgAs as]] [[KeyPgUinteger uinteger]] ) [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] [ [[KeyPgExport Export]] ]
	**Operator** //typename//.[[KeyPgOpDelete delete]] ( //buf//  [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] ) [ [[KeyPgExport Export]] ]
	**Operator** //typename//.[[KeyPgOpDelete delete]][] ( //buf//  [[KeyPgAs as]] [[KeyPgAny any]] [[KeyPgPtr ptr]] ) [ [[KeyPgExport Export]] ]
##
{{fbdoc item="param"}}
	##//typename//## 
		Name of the ##[[KeyPgType Type]]##, ##[[KeyPgClass Class]]##, ##[[KeyPgUnion Union]]##, or ##[[KeyPgEnum Enum]]##.
	##//assignment_op//## 
		##let += -= *= &= /= \= mod= shl= shr= and= or= xor= imp= eqv= ^=##
	##//unary_op//##
		##""-"" not * -> abs sgn fix frac int exp log sin asin cos acos tan atn len##
	##//binary_op//##
		##+ - * & / \ mod shl shr and or xor imp eqv ^ = <> < > <= >=##

{{fbdoc item="desc"}}
	The built in operators like ##=##, ##+##, and ##cast## have predefined behaviors when used in expressions.  These operators can be overloaded to do something other than predefined operations when at least one of the arguments to the operator is a ##[[KeyPgType Type]]##, ##[[KeyPgClass Class]]##, ##[[KeyPgEnum Enum]]##, or ##[[KeyPgUnion Union]]## data type.

	Operators are just functions.  The operator '+' has functionality like ##Function Plus( A as DataType, B as DataType ) as DataType##.  See //[[ProPgOperatorOverloading Operator Overloading]]// for more information.  Operators can be overloaded to accept different data types as parameters.  The ##[[KeyPgCast Cast]]## Operator is the only operator (or function) that can be declared multiple times when only the return type differs (for not explicit usage, the compiler may decide which cast overload to call based on how the object is used).

	Non-static operator members are declared inside the ##[[KeyPgType Type]]## or ##[[KeyPgClass Class]]##.  Global operators are declared outside.  All operator definitions (procedure bodies) must appear outside.

	##**Let**##, ##**Cast**##, and other assignment operators must be declared inside the ##[[KeyPgType Type]]## or ##[[KeyPgClass Class]]##.  They are passed a hidden ##[[KeyPgThis this]]## parameter and have a return data type same as the ##[[KeyPgType Type]]## or ##[[KeyPgClass Class]]## they are declared in.

	Unary operators must be declared outside the ##[[KeyPgType Type]]##, ##[[KeyPgClass Class]]##, or ##[[KeyPgEnum Enum]]## and have a return data type explicitly declared.  Unary operators can be overloaded to return any valid data type, except for ##[[KeyPgOpPtrMemberAccess Operator -> (Pointer to member access)]]## which must return a ##[[KeyPgType Type]]## or ##[[KeyPgClass Class]]## data type.

	Binary operators must be declared outside the ##[[KeyPgType Type]]##, ##[[KeyPgClass Class]]##, or ##[[KeyPgEnum Enum]]## and have a return data type explicitly declared.  Binary operators can be overloaded with valid data types, except for relational operators, which must return ##[[KeyPgInteger Integer]]##.

	##[[KeyPgLet Let]]## refers to the assignment operator, as in ##LET a=b##. The ##[[KeyPgLet Let]]## keyword is omitted in common practice, and is not allowed in the //[[CompilerOptlang -lang fb]]// dialect.  However, ##[[KeyPgOpLetlist Let()]]## can be used to assign the fields of a UDT to multiple variables.

	See ##[[KeyPgOpFor For]]##, ##[[KeyPgOpStep Step]]##, and ##[[KeyPgOpNext Next]]## for more information on overloading the ##[[KeyPgFornext For..Next]]## statement for use with user defined types.

	##**New**##, ##**New[]**##, ##**Delete**##, and ##**Delete[]**## operator members are always static, even if not explicitly declared (##[[KeyPgStaticMember static]]## keyword is unnecessary but allowed).

{{fbdoc item="ex"}}
{{fbdoc item="filename" value="examples/manual/udt/operator1.bas"}}%%(freebasic)
'' operator1.bas

Type Vector2D
  As Single x, y

  '' Return a string containing the vector data.
  Declare Operator Cast() As String

  '' Multiply the vector by a scalar.
  Declare Operator *= ( ByVal rhs As Single )
End Type

'' Allow two vectors to be able to be added together.
Declare Operator + ( ByRef lhs As Vector2D, ByRef rhs As Vector2D ) As Vector2D

'' Return the modulus (single) of the vector using the overloaded operator abs().
Declare Operator abs (  ByRef rhs As Vector2D ) As Single

Operator Vector2D.cast () As String
  Return "(" + Str(x) + ", " + Str(y) + ")"
End Operator

Operator Vector2D.*= ( ByVal rhs As Single )
  This.x *= rhs
  This.y *= rhs
End Operator

Operator + ( ByRef lhs As Vector2D, ByRef rhs As Vector2D ) As Vector2D
  Return type<Vector2D>( lhs.x + rhs.x, lhs.y + rhs.y )
End Operator

Operator abs ( ByRef rhs As Vector2D ) As Single
  Return Sqr( rhs.x * rhs.x + rhs.y * rhs.y )
End Operator

Dim a As Vector2D = type<Vector2D>( 1.2, 3.4 )
Dim b As Vector2D = type<Vector2D>( 8.9, 6.7 )
Dim c As Vector2D = type<Vector2D>( 4.3, 5.6 )

Print "a = "; a, "abs(a) ="; abs( a )
Print "b = "; b, "abs(b) ="; abs( b )
Print "a + b = "; a + b, "abs(a+b) ="; abs( a + b )
Print "c = "; c, "abs(c) ="; Abs( c )
Print "'c *= 3'"
c *= 3
Print "c = "; c, "abs(c) ="; Abs( c )
%%
	Aligned memory allocator:
		- by using the overloaded member operators "New" and "Delete", any created User object is aligned to a multiple of "ALIGN" bytes (256 bytes in this example),
		- the real pointer of the allocated memory is saved just above the User pointer, in the padding block.
{{fbdoc item="filename" value="examples/manual/udt/operator2.bas"}}%%(freebasic)
'' operator2.bas

Const ALIGN = 256

Type UDT
  Dim As Byte a(0 to 10 * 1024 * 1024 - 1) '' 10 megabyte fixed array
  Declare Operator New (Byval size As UInteger) As Any Ptr
  Declare Operator Delete (Byval buffer As Any Ptr)
  Declare Constructor ()
  Declare Destructor ()
End Type

Operator UDT.New (Byval size As UInteger) As Any Ptr
  Print "  Overloaded New operator, with parameter size = &h" & Hex(size)
  Dim pOrig As Any Ptr = Callocate(ALIGN-1 + Sizeof(UDT Ptr) + size)
  Dim pMin As Any Ptr = pOrig + Sizeof(UDT Ptr) 
  Dim p As Any Ptr = pMin + ALIGN-1 - (Culng(pMin + ALIGN-1) Mod ALIGN)
  Cast(Any Ptr Ptr, p)[-1] = pOrig
  Operator = p
  Print "  real pointer = &h" & Hex(pOrig), "return pointer = &h" & Hex(p)
End Operator

Operator UDT.Delete (Byval buffer As Any Ptr)
  Print "  Overloaded Delete operator, with parameter buffer = &h" & Hex(buffer)
  Dim pOrig As Any Ptr = Cast(Any Ptr Ptr, buffer)[-1]
  Deallocate(pOrig)
  Print "  real pointer = &h" & Hex(pOrig)
End Operator

Constructor UDT ()
  Print "  Constructor, @This = &h" & Hex(@This)
End Constructor

Destructor UDT ()
  Print "  Destructor, @This = &h" & Hex(@This)
End destructor

Print "'Dim As UDT Ptr p = New UDT'"
Dim As UDT Ptr p = New UDT

Print "  p = &h" & Hex(p)

Print "'Delete p'"
Delete p
%%
		Output example:
	%%
'Dim As UDT Ptr p = New UDT'
  Overloaded New operator, with parameter size = &hA00000
  real pointer = &h420020   return pointer = &h420100
  Constructor, @This = &h420100
  p = &h420100
'Delete p'
  Destructor, @This = &h420100
  Overloaded Delete operator, with parameter buffer = &h420100
  real pointer = &h420020
%%
	Small use case of the operator "[]": simplest smart pointers for byte buffers.
{{fbdoc item="filename" value="examples/manual/udt/operator3.bas"}}%%(freebasic)
'' operator3.bas

'' 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.

'' Example of simplest smart pointers for byte buffers:
'' - Constructor and destructor allow to allocate, deallocate, and resize the byte buffer.
'' - Pointer index operator allows to access buffer elements.
'' - Copy-constructor and let-operator are just declared in private section,
''   in order to disallow copy construction and any assignment.

Type smartByteBuffer
  Public:
	Declare Constructor (Byval size As Uinteger = 0)
	Declare Operator [] (Byval index As Uinteger) Byref As Byte
	Declare Destructor ()
  Private:
	Declare Constructor (Byref rhs As smartByteBuffer)
	Declare Operator Let (Byref rhs As smartByteBuffer)
	Dim As Byte PTR psbb
End Type

Constructor smartByteBuffer (Byval size As Uinteger = 0)
  This.destructor()
  If size > 0 Then
	This.psbb = New Byte[size]
	Print "Byte buffer allocated"
  End If
End Constructor

Operator smartByteBuffer.[] (Byval index As Uinteger) Byref As Byte
  Return This.psbb[index]
End Operator

Destructor smartByteBuffer ()
  If This.psbb > 0 Then
	Delete[] This.psbb
	This.psbb = 0
	Print "Byte buffer deallocated"
  End If
End destructor

Scope
  Dim As smartByteBuffer sbb = smartByteBuffer(256)
  For I As Integer = 0 To 255
	sbb[I] = I - 128
  Next I
  Print
  For I As Integer = 0 To 255
	Print Using "#####"; sbb[I];
  Next I
  Print
End Scope
%%
{{fbdoc item="lang"}}
	- Only available in the //[[CompilerOptlang -lang fb]]// dialect.

{{fbdoc item="see"}}
	- ##[[KeyPgClass Class]]##
	- ##[[KeyPgClass Enum]]##
	- ##[[KeyPgType Type]]##

{{fbdoc item="back" value="CatPgUserDefTypes|User Defined Types"}}