2012年6月13日水曜日

boost::ptr_vector を使ったら、死ねたでござる(ToT)


#include <boost/ptr_container/ptr_vector.hpp>
#include <algorithm>
#include <iostream>


struct sineru {
  int i_;
  sineru(int i) : i_(i) { std::cout << "sineru::sineru(" << (void*)this << ")" << std::endl; }
  ~sineru() { std::cout << "sineru::~sineru(" << (void*)this << ")" << std::endl; }

  bool operator < (const sineru& rhs) const { return i_ < rhs.i_; }

};


int main() {
  boost::ptr_vector<sineru> v;

  for( int i = 5; i > 0; --i ) v.push_back( new sineru(i) );
  std::sort( v.begin(), v.end() );
 
  std::cout << "====== sorted ======" << std::endl;
 
  return 0;

}
実行結果
sineru::sineru(003B20C8)
sineru::sineru(003B2148)
sineru::sineru(003B2138)
sineru::sineru(003B2158)
sineru::sineru(003B2168)
sineru::~sineru(0018FE48)
sineru::~sineru(0018FE48)
sineru::~sineru(0018FE48)
sineru::~sineru(0018FE48)
====== sorted ======
sineru::~sineru(003B20C8)
sineru::~sineru(003B2148)
sineru::~sineru(003B2138)
sineru::~sineru(003B2158)
sineru::~sineru(003B2168)
 おいどんが、悪かったでごわす。move が導入されるまで、もう2度と ptr_container は、使いたくないでごわす。

boost range unique 備忘録

#include <iostream>
#include <vector>
#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm_ext.hpp>

void s( int n ) { std::cout << n << ","; }

int main() {
  std::vector<int> v;
  for( int i = 0; i < 20; ++i ) {
    v.push_back( (21-i) / 2 );
  }

  boost::for_each( v, s );
  std::cout << std::endl;
  boost::erase(v, boost::unique<boost::return_found_end>(boost::sort(v)));

  // boost::return_next_end は、document 間違い?
  // と思ったら、++i と消去する寸前にイテレータをインクリメントしてました… orz
  // http://www.boost.org/doc/libs/1_49_0/libs/range/doc/html/range/reference/algorithms/introduction.html
  /*
  boost::sort(v);
  boost::erase(v, boost::unique<boost::return_next_end>(v));
  */
  boost::for_each( v, s );

  return 0;
}
出力
10,10,9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1
1,2,3,4,5,6,7,8,9,10,
// コメントアウトを実行すると
1,2,3,4,5,6,7,8,9,10,6
追記:ドキュメントを良く見たら、間違いではなかったので訂正しました。

2012年6月8日金曜日

今更 c++ で hello world

上っ面だけでは判断できませんが、以下のコードは UTF-8 で書かれています。
#include <iostream>

int main() {
  std::cout << "こんにちわ世界" << std::endl;
 return 0;
}

 mac 環境にて、 gcc-4.2.1 と clang++ 3.1 の両方でコンパイルして実行してみました。
$ clang++ hello.cpp
$ ./a.out
  こんにちわ世界
そらまー、そうですよねー。調子こいて、もうひとつ
#include <iostream>

int main(){
  std::cout << "こんにちわ世界" << std::endl;
  std::cout << "おはよー" << std::endl;
  std::cout << "Good Morning-." << std::endl;
  std::cout << "早上好ー" << std::endl;
  std::cout << "早晨ー" << std::endl;
  std::cout << "Bonjour!" << std::endl;
  std::cout << "Buenos dias-." << std::endl;
  std::cout << "안녕하십니까?" << std::endl;
  std::cout << "Доброе утро." << std::endl;
  std::cout << "Bom dia-." << std::endl;
  std::cout << "Buon giorno-." << std::endl;
  std::cout << "Guten Morgen." << std::endl;
  return 0;
}
 ほれ
$ clang++ hello.cpp
$ ./a.out
  こんにちわ世界
  おはよー
  Good Morning-.
  早上好ー
  早晨ー
  Bonjour!
  Buenos dias-.
  안녕하십니까?
  Доброе утро.
  Bom dia-.
  Buon giorno-.
  Guten Morgen.
 そらまー、そうですよねー。妙な感動がありますな…。  ツッコミ入りそうなんで、書いとくと windows でも コードページ 65001 を指定すると、基本、同じ事になります。 試してないです。
c:¥>chcp 65001

boost::range 配列添字を処理するテスト

レンジでチーンと気分よくコード書いてたら、実は、後で、どの位置から取ってきたかを記録しときたい事に気がつきました。なんとなく危険な香りがするので、テストコードを書いて見ることに…なるほど…
#include <boost/range/algorithm/for_each.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
#include <vector>

struct hoge {
  hoge( int i ) : i_(i) {} 
  int i_;
};

void func( const hoge& h, int pos ) {
  std::cout << pos << ",";
}

void func2( const hoge& h, int& pos ) {
  std::cout << pos++ << ",";
}

int main() {

  std::vector<hoge> v;
  for( int i = 0; i < 10; ++i ) v.push_back( i );

  int n = 0;
  boost::for_each( v, boost::bind( func, _1, n++ ) );

  std::cout << std::endl;

  n = 0;
  boost::for_each( v, boost::bind( func2, _1, boost::ref(n) ) );


  return 0;

}

結果 vc8
0,0,0,0,0,0,0,0,0,0
0,1,2,3,4,5,6,7,8,9
 フィルターをかましたら、添字の位置もズレてしまうんで、zip して渡す方がスマートなのかも…暇があったら試してみるかな?

2012年6月7日木曜日

boost::geometry と gdal/ogr

普通にやるには、GDAL/OGR にて、geos を有効にしてコンパイルすれば何の問題もないです。 単に boost::geometry を使ってみたかっただけという…  concepts ベースで書いてみようかなとも思ったんですが、OGRPolygon あたりの実装を concept で書くのは、自分には無理ゲーっぽいと思ったので相互変換のコードでお茶を濁しました。お陰で、だいぶ geometry の concept についても、わかってきたのですが・・・。このポストが、役に立つ人っているのかいな?という疑問が無いわけでもない…。
#include <ogrsf_frmts.h>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/assign.hpp>

BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian);

namespace bg = boost::geometry;

typedef bg::model::d2::point_xy<double>    bg_point;
typedef bg::model::ring<bg_point>          bg_ring;
typedef bg::model::polygon<bg_point>       bg_polygon;
typedef bg::model::linestring<bg_point>    bg_linestring;

void point2ogrpoint(OGRPoint& lhs, const bg_point& rhs);
void line2ogrline(OGRLineString& lhs, const bg_linestring& rhs);
void poly2ogrpoly(OGRPolygon& lhs, const bg_polygon& rhs);
bg_point ogrpoint2point( const OGRPoint& rhs );
bg_linestring ogrline2line( const OGRLineString& rhs );
bg_polygon ogrpoly2poly( const OGRPolygon& rhs );



using namespace boost::assign;

void point2ogrpoint(OGRPoint& lhs, const bg_point& rhs) {
  lhs.setX( bg::get<0>(rhs) );
  lhs.setY( bg::get<1>(rhs) );
} 

void line2ogrline(OGRLineString& lhs, const bg_linestring& rhs) {
  lhs.setNumPoints( rhs.size() );
  for( int i = 0; i < rhs.size(); ++i ) {
    lhs.setPoint( i, bg::get<0>(rhs[i]), bg::get<1>(rhs[i]), 0.0 );
  }
}

void ring2ogrring(OGRLinearRing& lhs, const bg_ring& rhs) {
  lhs.setNumPoints( rhs.size() );
  for( int i = 0; i < rhs.size(); ++i ) {
    lhs.setPoint( i, bg::get<0>(rhs[i]), bg::get<1>(rhs[i]), 0.0 );
  }
}

void poly2ogrpoly(OGRPolygon& lhs, const bg_polygon& rhs) {
  { // external ring
    OGRLinearRing externalRing;
    ring2ogrring( externalRing, rhs.outer() );
    lhs.addRing( &externalRing );
  }
  // internal rings
  for( int i = 0; i < rhs.inners().size(); ++i ) {
    OGRLinearRing internalRing;
    ring2ogrring( internalRing, rhs.inners()[i] );
    lhs.addRing( &internalRing );
  }
}

bg_point ogrpoint2point( const OGRPoint& rhs ) {
  return bg_point( rhs.getX(), rhs.getY() );
}

bg_linestring ogrline2line( const OGRLineString& rhs ) {
  bg_linestring result;
  for( int i = 0; i < rhs.getNumPoints(); ++i ) {
    result += bg_point( rhs.getX(i), rhs.getY(i) );
  }
  return result;
}

bg_ring ogrring2ring( const OGRLinearRing& rhs ) {
  bg_ring result;
  for( int i = 0; i < rhs.getNumPoints(); ++i ) {
    result += bg_point( rhs.getX(i), rhs.getY(i) );
  }
  return result;
}

bg_polygon ogrpoly2poly( const OGRPolygon& rhs ) {
  bg_polygon result;
  result.outer() = ogrring2ring( *(rhs.getExteriorRing()) );
  int n = rhs.getNumInteriorRings();
  for( int i = 0; i < n; ++i ) {
    result.inners().push_back( ogrring2ring(*(rhs.getInteriorRing( i ))) );
  }
  return result;
}

2012年6月6日水曜日

std::floor の挙動

やっぱり、しょうもない事でもコードを書いて確認したくなるのであった。 本日は、std::floor が負の値をちゃんと負方向に切り捨ててるか?
#include <iostream>
#include <cmath>

int main() {
  std::cout << static_cast<int>(  0.5 / 10 ) << std::endl;
  std::cout << static_cast<int>( -0.5 / 10 ) << std::endl;
  std::cout << static_cast<int>( std::floor( 0.5 / 10.0 ) ) << std::endl;
  std::cout << static_cast<int>( std::floor( -0.5 / 10.0 ) ) << std::endl;
  std::cout << static_cast<int>( std::floor( 0.5 / 10 ) ) << std::endl;
  std::cout << static_cast<int>( std::floor( -0.5 / 10 ) ) << std::endl;
  return 0;
}

/*  // 実行結果は、VC8
  0
  0
  0
  -1
  0
  -1  // 微妙かも?
*/

2012年6月3日日曜日

luabind のコンパイルでエラー: トークン "(" の前に二項演算子がありません

昨日は祟られてたのだ・・・。久しぶりにubuntu環境でコンパイルしようと思ったら、Google Chrome がハングしまくりで、キーボードもマウスも反応しなくなり、強制電源オフの刑を食らいまくった。
$ ps aux | grep chrome
で表示される chrome のプロセス数の多さには閉口するのな。運良くプロセス番号を見つける事ができたら
$ kill -9 XXXXXXX
で、chrome 死にさらせーーーーーーーーーて爽快に叫んでるところなんですが、「このページは応答していません」のメッセージと共にシステムを道連れにして何もできなくなるのな。サーバじゃないし、家には一台しかパソくん無いから、ssh で入ってとか無しです。これの繰り返し・・・。 (#・∀・)ムカッ!!ときて、ubuntu からは、chrome 削除しました。いやー、快適です。  それで本題に入ります。boost のコンパイルが、また嵌りまくった。
$ ./b2 stage --without-mpi --without-python --build-type=complete --layout=versioned
でやると、コンパイルをしてくれるんだけど、
$ ./b2 stage --without-mpi --without-python --build-type=complete --layout=versioned install
でやると、HAS_LONG_DOUBLE_SUPPORT の所で、ずーっと黙りこくったまま応答を返さない。 (#・∀・)ムカッ!!ときて、もうええねん、ライブラリ手動でコピーして、シンボリックリンクも自分でやればええんやろ? とプンプンしながら、luabind をコンパイルしようとしたら
$ cd /usr/local/src/luabind*
$ export BOOST_ROOT=/usr/local/src/boost_1_49_0
$ export BOOST_BUILD_PATH=/usr/local/src/boost_1_49_0/tools/build/v2
$ ../boost_1_49_0/b2 --build-type=complete --layout=versioned
って、やったら、「エラー: トークン "(" の前に二項演算子がありません」の嵐… どうも、gcc-4.6 とか、あかんのかな? 最終的には、 BOOST_PP_ITERATION_FLAGS(): error: missing binary operator before token "(” という情報に辿りつきました。疲れた・・・