多重定義演算子
For,
Next,
Step を使うと、For ... Next ループのユーザー定義型
反復子(組み込みスカラー型反復子だけではなく)を構築できます。
構文 (宣言)
用法
For iterator [ As
typename ] =
start_value To
end_value [
Step step_value ]
[ ...statements... ]
Next
For...Next 命令文で
step_value が指定されていない場合は、演算子の最初の構文が使われます。
step_value が指定されている場合は、2番目の構文が使われ、step オブジェクト(
step-value で初期化された)が
stp パラメーターを介して渡されます:
演算子の両方の構文は、同じユーザー定義型で共存できます(メンバーの多重定義のおかげ)(ユーザーコードの
For...Next 命令文で明示的な増分を使用する場合と、使用しない場合の両方で)。
パラメータ
(including arguments)
typename
stp,
step_value
a typename object used as an incremental value
iterator
a typename object used as an iterator
cond,
end_value
a typename object used as a loop-terminating value
start_value
a typename object used to copy construct or assign to the iterator initially
説明
演算子 For,
演算子 Next,
演算子 Step は、ユーザー定義型定義で多重定義して、その型のオブジェクトを(組み込みスカラー型に対して事前定義されている代わりに)
For...Next ループで反復子およびステップ値として使えるようにすることができます。
すべての非静的メンバー手続きとして、3つの演算子は、反復子オブジェクト(
For...Next 命令文から
start_value 引数値に初期化されている)への参照によるアクセスを許可する、非表示
this パラメーターを渡しました。
Operator Next の
cond パラメーターを使うと、
For...Next 命令文から
end_value 引数値にアクセスできます。
For...Next 命令文で
step_value が(引数として)指定されている場合、
stp パラメーターにより、3つの演算子で、この値にアクセスできます。
注: For...Next 命令文で
step_value が指定されていない場合(暗黙的なステップ)、ユーザー定義型には、デフォルトのコンストラクター(暗黙的または明示的)または変換コンストラクターが必要です。
ユーザーがデフォルトのコンストラクターを定義しても、
For...Next ループを初期化するときにコンパイラーがそれを使わないのは、現時点のバグです。
演算子 For
演算子 For は、コピーを作成するか、反復子オブジェクトに割り当て(
start_value を使用)た直後に 1回呼び出され、終了オブジェクトを作成(
end_value を使用)し、ステップオブジェクトを作成(
For...Next 命令文で定義されている場合は
step_value を使用)します。
演算子 For を使うと、ループの準備に必要な追加の初期化を実行できます。
演算子 Next
演算子 Step
高度な使い方
上記の説明で、3つの引数
start_value,
end_value,
step_value は
iterator と同じ型(これは明白な使い方です)でなければならないように思われますが、そうではありません:
- start_value, end_value, step_value の各引数は、任意の型を使えます(それらの間で異なる型であっても、iterator の型と異なる型であっても構いません)。
- 唯一の制約は、start_value 引数から iterator が構築(ローカル iterator の場合)または代入(グローバル iterator の場合)できる可能性があることです(iterator は暗黙のうちに構築または代入されるからです)。
- 同様に、他の引数 end_value と step_value は、iterator と同じ型のオブジェクトに変換できなければなりません。
アルゴリズム
3つの多重定義演算子の周りの
For...Next ループアルゴリズム:
' FOR...NEXT loop
' V
' |
' constructing/assigning iterator object
' (This = start_value from For...Next statement)
' |
' constructing end object
' (cond = end_value from For...Next statement)
' |
' if step_value is defined >---------------------.
' else :
' v v
' : constructing step object
' : (stp = step_value from For...Next statement)
' : :
' :<----------------------------------'
' |
' calling Operator For
' |
' .----------------------->|
' | |
' | calling Operator Next
' | (if end-condition verified: =0 returned) >-------------.
' | (else: <>0 returned) |
' | v |
' | | |
' | executing For...Next body |
' | | |
' | calling Operator Step |
' | | |
' '------------------------' |
' |
' V
例
暗黙的なステップ値を使って、画面解像度を反復処理するための型:
Type screenResolution
' user interface
Declare Constructor (ByVal colorBit As Long)
Declare Property colorDepth () As Long
Declare Property screenWidth () As Long
Declare Property screenHeigth () As Long
' overload iteration operators when Step is not defined in For...Next statement
Declare Operator For ()
Declare Operator Next (ByRef iterateCondition As screenResolution) As Integer
Declare Operator Step ()
' internal variables
Dim As Long colorBit, resolutionWH
End Type
Constructor screenResolution (ByVal colorBit As Long)
This.colorBit = colorBit
End Constructor
Property screenResolution.colorDepth () As Long
Return This.colorBit
End Property
Property screenResolution.screenWidth () As Long
Return HiWord(This.resolutionWH)
End Property
Property screenResolution.screenHeigth () As Long
Return LoWord(This.resolutionWH)
End Property
Operator screenResolution.For ()
This.resolutionWH = ScreenList(This.colorBit)
End Operator
Operator screenResolution.Next (ByRef iterateCondition As screenResolution) As Integer
While This.resolutionWH = 0
If This.colorBit < iterateCondition.colorBit Then
This.colorBit += 1
This.resolutionWH = ScreenList(This.colorBit)
Else
Exit While
End If
Wend
Return (This.resolutionWH <> iterateCondition.resolutionWH)
End Operator
Operator screenResolution.Step ()
This.resolutionWH = ScreenList()
End Operator
Print "Screen resolutions supported within [1 bpp , 64 bpp]:"
For iterator As screenResolution = screenResolution(1) To screenResolution(64)
Print " " & iterator.colorDepth & " bpp ",
Print ":" & iterator.screenWidth & "x" & iterator.screenHeigth
Next iterator
Print "End of supported screen resolutions"
Sleep
出力例:
Screen resolutions supported within [1 bpp , 64 bpp]:
24 bpp :320x200
24 bpp :320x240
24 bpp :400x300
24 bpp :512x384
24 bpp :640x400
24 bpp :640x480
24 bpp :800x600
24 bpp :1024x768
24 bpp :1152x864
24 bpp :1280x600
24 bpp :1280x720
24 bpp :1280x768
24 bpp :1280x800
24 bpp :1280x960
24 bpp :1280x1024
24 bpp :1360x768
24 bpp :1366x768
24 bpp :1400x1050
24 bpp :1440x900
24 bpp :1600x900
24 bpp :1680x1050
24 bpp :1920x1080
32 bpp :320x200
32 bpp :320x240
32 bpp :400x300
32 bpp :512x384
32 bpp :640x400
32 bpp :640x480
32 bpp :800x600
32 bpp :1024x768
32 bpp :1152x864
32 bpp :1280x600
32 bpp :1280x720
32 bpp :1280x768
32 bpp :1280x800
32 bpp :1280x960
32 bpp :1280x1024
32 bpp :1360x768
32 bpp :1366x768
32 bpp :1400x1050
32 bpp :1440x900
32 bpp :1600x900
32 bpp :1680x1050
32 bpp :1920x1080
End of supported screen resolutions
3つの演算子で明示的なステップ値を使って、分数を反復するための型:
(
演算子 Step ページのプログラムに比べて改善された例)
Type fraction
' user interface
Declare Constructor (ByVal n As Integer, ByVal d As Integer)
Declare Operator Cast () As String
' overload iteration operators when Step is defined in For...Next statement
Declare Operator For (ByRef iterateStep As fraction)
Declare Operator Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
Declare Operator Step (ByRef step_var As fraction)
' internal variables and cast operator
As Integer num, den
Declare Operator Cast () As Double
End Type
Constructor fraction (ByVal n As Integer, ByVal d As Integer)
This.num = n
This.den = d
End Constructor
Operator fraction.Cast () As String
' search for the highest common factor (a) between numerator and denominator
Dim As Integer a = Abs(This.num), b = Abs(This.den)
If a <> 0 Then
While a <> b
If a > b Then
a -= b
Else
b -= a
End If
Wend
Else
a = 1
End If
' reduce the fraction
Return num \ a & "/" & den \ a
End Operator
Operator fraction.Cast () As Double
Return This.num / This.den
End Operator
Operator fraction.For (ByRef iterateStep As fraction)
' search for the least common multiple (a) between the two denominators
Dim As Integer a = Abs(This.den), b = Abs(iterateStep.den), c = a, d = b
While a <> b
If a > b Then
b += d
Else
a += c
End If
Wend
' align at the same denominator the 2 fractions
This.num *= a \ This.den
This.den = a
iterateStep.num *= a \ iterateStep.den
iterateStep.den = a
End Operator
Operator fraction.Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
If iterateStep.num < 0 Or iterateStep.den < 0 Then
Return This >= iterateCondition
Else
Return This <= iterateCondition
End If
End Operator
Operator fraction.Step (ByRef iterateStep As fraction)
This.num += iterateStep.num
End Operator
Print "iteration from 1/8 to 1/2 by step of 1/12:"
For iterator As fraction = fraction(1, 8) To fraction(1, 2) Step fraction(1, 12)
Print " " & iterator;
Next
Print
Print
Print "iteration from 7/10 to -8/5 by step of -8/15:"
For iterator As fraction = fraction(7, 10) To fraction(-8, 5) Step fraction(-8, 15)
Print " " & iterator;
Next
Print
Sleep
出力:
iteration from 1/8 to 1/2 by step of 1/12:
1/8 5/24 7/24 3/8 11/24
iteration from 7/10 to -8/5 by step of -8/15:
7/10 1/6 -11/30 -9/10 -43/30
参照