路傍のプログラマ

只のプログラマが綴る愚痴と備忘録

boost::optionalはループでも便利

2007-06-01 20:59:03 | プログラミング
C++向けライブラリboostにあるboost::optionalは、
値がない状態(初期化すらされていない状態)を表現できる仕組みです。

例題では、
double sqrt(double n );
で、n < 0のときは戻り値がないことを示すために、
boost::optional<double> sqrt(double n);
とする例が挙げられています。

ちなみに、使う側は、(あたかもポインタのように)値があるかをチェックして、その後使う、という風にします。
boost::optional<double> value = sqrt(なにか計算式);
if (value) {
 std::cout << "答え: " << *value << std::endl;
} else {
 std::cout << "解なし" << std::endl;
}

boost::optionalの例題はネットで見る限り、なぜか関数の戻り値の例ばかりです。
が、実際に使ってみると、なかなかどうして、boost::optionalはちょっとした
ループでも便利に使えることがわかります。

たとえば、繰り返しの直前の値を保持する例。

template<typename IterT, typename ValueT>
void print_unique_values_in_sorted_sequence(IterT begin, IterrT end)
{
 boost::optional<ValueT> lastValue;
 for (IteratorType i = begin; i != end; ++i) {
  if (! (lastValue && *i == *lastValue))
   std::cout << *i << std::endl;
  lastValue = *i;
 }
}

あるいは、条件を満たすものが見つかったときに、その値を保持する例。

boost::optional<size_t> smallGapIndex;
boost::optional<size_t> largeGapIndex;
for (size_t i = 0; i + 1 < ary.size(); ++i) {
 double diff = fabs(ary[i + 1] - ary[i]);
 if (! smallGapIndex && diff < 0.0001)
  smallGapIndex = i;
 if (! largeGapIndex && diff > 1000.0)
  largeGapIndex = i;
 if (smallGapIndex && largeGapIndex)
  break; // for i
}
if (smallGapIndex)
 std::cout << "small gap index = " << *smallGapIndex << std::endl;
if (largeGapIndex)
 std::cout << "large gap index = " << *largeGapIndex << std::endl;

公開するAPIにboostの文字を入れるのは禁止されているときでも、
こういうこそっとした使い方ならお目こぼしになる可能性もありますし。
おすすめです。

(最初、boost::optionalの実装って、本当はポインタを持ってヒープを
割り当ててるんじゃないかと疑いつつ、optional.hppを見たのですが、
いやもう、とても鍛えられたコードでした。疑ってごめんなさい)

情報リテラシーがないから?

2007-06-01 00:27:07 | その他
「ITの影の恐ろしさ認識」全日空社長が陳謝
http://www.asahi.com/national/update/0531/TKY200705310308.html

「ITに頼って便利になったが」って完全に人ごとだし。

「恐ろしさを十分認識した」って、何を今さら。

90年代に、米国でも、システムのバグがとれないとかで、デンバー空港の開港が1年以上遅れて数億ドルの損失、とかあったんだけど、知らないんだろうか。