Boost Phoenix はとても便利ですが、もしその使用が許されない場面で標準の functional で代替する場合の対応表を演算子の優先順位で書いてみました。
演算子 |
Name | functional |
例 |
Boost Phoenixでの例 |
. |
ドット(Element selection by reference) | mem_fun_ref |
transform(a.begin(),a.end(),b.begin(),mem_fun_ref(&string::size)) |
bind(&string::size,_1) |
-> |
アロー(Element selection through pointer) | mem_fun |
transform(a.begin(),a.end(),b.begin(),mem_fun(&string::size)) |
bind(&string::size,_1) |
- |
単項負(Unary minus) | negate<T> |
transform(a.begin(),a.end(),b.begin(),negate<int>()) |
-_1 |
& |
単項アドレス(Address-of) | ptr_fun |
transform(a.begin(),a.end(),b.begin(),ptr_fun(&atoi)) |
bind(&atoi,_1) |
! |
単項論理否定(Unary Logical NOT) | not1 |
count_if(a.begin(),a.end(),not1(bind2nd(modulus<int>(),2))) |
!(_1 % 2) |
! |
単項論理否定(Unary Logical NOT) | logical_not<T> |
transform(a.begin(),a.end(),b.begin(),logical_not<bool>()) |
!_1 |
~ |
単項ビット否定(Unary Bitwise NOT) | bitwise_not<T> |
transform(a.begin(),a.end(),b.begin(),bitwise_not<int>()) |
~_1 |
* |
二項乗(Multiplication) | multiplies<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),multiplies<int>()) |
_1 * _2 |
/ |
二項除(Division) | divides<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),divides<int>()) |
_1 / _2 |
% |
二項法(Modulus) | modulus<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),modulus<int>()) |
_1 % _2 |
+ |
二項加(Addition) | plus<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),plus<int>()) |
_1 + _2 |
- |
二項減(Subtraction) | minus<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),minus<int>()) |
_1 - _2 |
<< |
ビット左シフト(Bitwise left shift) | bitshift_left<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),bitshift_left<int>()) |
_1 << _2 |
>> |
ビット右シフト(Bitwise right shift) | bitshift_right<T> |
transform(a.begin(),a.end(),b.begin(),c.begin(),bitshift_right<int>()) |
_1 >> _2 |
< |
関係不等号(Relational "less than") | less<T> |
sort(a.begin(),a.end(),less<int>()) |
_1 < _2 |
<= |
関係不等号(Relational "less than or equal to") | less_equal<T> |
count_if(a.begin(),a.end(),bind2nd(less_equal<int>(),4)) |
_1 <= 4 |
> |
関係不等号(Relational "greater than") | greater<T> |
sort(a.begin(),a.end(),greater<int>()) |
_1 > _2 |
>= |
関係不等号(Relational "greater than or equal to") | greater_equal<T> |
count_if(a.begin(),a.end(),bind2nd(greater_equal<int>(),4)) |
_1 >= 4 |
== |
関係等号(Relational "equal to") | equal_to<T> |
count_if(a.begin(),a.end(),bind2nd(equal_to<int>(),4)) |
_1 == 4 |
!= |
関係不等号(Relational "not equal to") | not_equal_to<T> |
count_if(a.begin(),a.end(),bind2nd(not_equal_to<int>(),4)) |
_1 != 4 |
!= |
関係不等号(Relational "not equal to") | not2 |
mismatch(a.begin(),a.end(),b.begin(),not2(equal_to<int>())) |
!(_1 == _2) |
& |
ビットAND(Bitwise AND) | bitwise_and<T> |
transform(a.begin(),a.end(),b.begin(),c.end(),bitwise_and<int>()) |
_1 & _2 |
^ |
ビットXOR(Bitwise XOR) | bitwise_xor<T> |
transform(a.begin(),a.end(),b.begin(),c.end(),bitwise_xor<int>()) |
_1 ^ _2 |
| |
ビットOR(Bitwise OR) | bitwise_or<T> |
transform(a.begin(),a.end(),b.begin(),c.end(),bitwise_or<int>()) |
_1 | _2 |
&& |
論理AND(Logical AND) | logical_and<T> |
transform(a.begin(),a.end(),b.begin(),c.end(),logical_and<bool>()) |
_1 && _2 |
|| |
論理OR(Logical OR) | logical_or<T> |
transform(a.begin(),a.end(),b.begin(),c.end(),logical_or<bool>()) |
_1 || _2 |
但し、表中のビット演算子は functional にはなぜか存在しませんので、more_functional で拵えました。
また、Boost Bind では、論理演算子については直感的に使えるようオーバーロードされているので、Boost Phoenix との対比を兼ねて表にしてみました。
演算子 |
Boost Bind |
例 |
Boost Phoenixでの例 |
. |
bind(〜,_1) |
transform(a.begin(),a.end(),b.begin(),bind(&string::size,_1)) |
bind(&string::size,_1) |
-> |
bind(〜,_1) |
transform(a.begin(),a.end(),b.begin(),bind(&string::size,_1)) |
bind(&string::size,_1) |
& |
bind(〜,_1) |
transform(a.begin(),a.end(),b.begin(),bind(&atoi,_1)) |
bind(&atoi,_1) |
! |
!bind(〜) |
transform(a.begin(),a.end(),b.begin(),!bind(modulus<int>(),_1,2)) |
!(_1 % 2) |
< |
bind(〜) < bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) < bind(modulus<int>(),_1,3)) |
_1 % 2 < _1 % 3 |
<= |
bind(〜) <= bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) <= bind(modulus<int>(),_1,3)) |
_1 % 2 <= _1 % 3 |
> |
bind(〜) > bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) > bind(modulus<int>(),_1,3)) |
_1 % 2 > _1 % 3 |
>= |
bind(〜) >= bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) >= bind(modulus<int>(),_1,3)) |
_1 % 2 >= _1 % 3 |
== |
bind(〜) == bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) == bind(modulus<int>(),_1,3)) |
_1 % 2 == _1 % 3 |
!= |
bind(〜) != bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) != bind(modulus<int>(),_1,3)) |
_1 % 2 != _1 % 3 |
&& |
bind(〜) && bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) && bind(modulus<int>(),_1,3)) |
_1 % 2 && _1 % 3 |
|| |
bind(〜) || bind(〜) |
transform(a.begin(),a.end(),b.begin(),bind(modulus<int>(),_1,2) || bind(modulus<int>(),_1,3)) |
_1 % 2 || _1 % 3 |
さて、more_functional で拵えたビット演算子ですが、これが有用なのは Hacker's Delight 第2章 BASICS「Manipulating Rightmost Bits」で紹介されている公式を保持できるようになるからですが、それを Boost Phoenix & Bind に対比させた形で以下にまとめておきます。
formula | Phoenix |
Boost Bind |
説明 |
\(x \& x - 1\) | _1 & _1-1 |
bind(bitwise_and<T>(),_1,bind(minus<T>(),_1,1)) |
最右1のビットをオフにする |
\(x | x + 1\) | _1 | _1+1 |
bind(bitwise_or<T>(),_1,bind(plus<T>(),_1,1)) |
最右0のビットをオンにする |
\(x \& x + 1\) | _1 & _1+1 |
bind(bitwise_and<T>(),_1,bind(plus<T>(),_1,1)) |
最右0のビットと末尾まで続く1をオフにする |
\(x | x - 1\) | _1 | _1-1 |
bind(bitwise_or<T>(),_1,bind(minus<T>(),_1,1)) |
最右1のビットを末尾まで満たす |
\(¬x \& x + 1\) | ~_1 & _1+1 |
bind(bitwise_and<T>(),bind(bitwise_not<T>(),_1),bind(plus<T>(),_1,1)) |
最右0のビットを1のビットとして取り出す |
\(¬x | x - 1\) | ~1 | _1-1 |
bind(bitwise_or<T>(),bind(bitwise_not<T>(),_1),bind(minus<T>(),_1,1)) |
最右1のビットを0のビットとして取り出す |
\(¬x \& x - 1\) | ~_1 & _1-1 |
bind(bitwise_and<T>(),bind(bitwise_not<T>(),_1),bind(minus<T>(),_1,1)) |
末尾まで続く0を1のビット列として取り出す |
\(¬x | x + 1\) | ~_1 | _1+1 |
bind(bitwise_or<T>(),bind(bitwise_not<T>(),_1),bind(plus<T>(),_1,1)) |
末尾まで続く1を0のビット列として取り出す |
\(x \& -x\) | _1 & -_1 |
bind(bitwise_and<T>(),_1,bind(negate<T>(),_1)) |
最右1のビットを1のビットとして取り出す |
\(x ⊕ x - 1\) | _1 ^ _1-1 |
bind(bitwise_xor<T>(),_1,bind(minus<T>(),_1,1)) |
最右1のビットと末尾まで続く0を1のビット列として取り出す |
\(x ⊕ x + 1\) | _1 ^ _1+1 |
bind(bitwise_xor<T>(),_1,bind(plus<T>(),_1,1)) |
最右0のビットと末尾まで続く1を1ビット列として取り出す |
つーか、記事の表組の中で MathJax+Unicode を試したかっただけですけど。