C++ functional, Boost Bind and Boost Phoenix

ID: 21
creation date: 2013/02/26 15:36
modification date: 2013/02/27 13:21
owner: taiji
tags: C++, functional, Boost Bind, Boost Phoenix, operator

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 を試したかっただけですけど。

0 コメント
ゲストコメント認証用なぞなぞ:
キーボードのLから左に全部打って下さい。それを二回やって下さい。 ...