読者です 読者をやめる 読者になる 読者になる

にほんごのれんしゅう

日本語として伝えるための訓練を兼ねたテクログ

boost::optionalを使ってみて 第一回

boost::optionalを使ってみて 第一回

boost::optionalをやってみました.C++でOption型を実現する例のアレ.
scalaのmatch caseがあまりに便利なので同等のものがほしかったのだけど,結局冗長に書くことでしか実現できなそう.
第一回ということは,まだあきらめてないのです,一応.

boost::optionalで容易に多相を実現できない

どこか,昔の彼方で見たときは,確かboost::optionalは有効状態のときには,int型を返し,無効状態のときにはnull_ptrを返却する,,,というものだったはず.(あとでよく仕様を確認)
地雷1:仮に想像通りの仕様だったとしても,C++の変数は次のようにauto宣言で,二つの状態を持たすことができない.

  boos::optional<int> hoge = Noneか実数値;    
  auto type = ([](auto x){if(x){return *x;}else{return nullptr;};})(hoge);//lambdaのauto xは多相になりうるが,変数のtypeは多相にできない.  

地雷2:コンパイル時に多相が確定するほど,boostの実装は楽でない.

結局scalaのようなsyntax sugerを実現するには,相当な努力が必要

TODOとして以下のものを残した. TODOを解決したとしても,楽なプロシージャになる気がしない
- templateで'boost::option'ならば,if文でboost::optionに対しては別のプロシージャが走るように細工が必要.
- 実行時の返り値の型が多相にならざる得ないので,返り値を束縛して保持するように第2引数はstd::function<void()> = std::bind(lambdaプロシージャ, lamdbaの中で処理する値の戻り値の参照かポインタ)を行う
- 全体的に使用時のシンタックスがわかりやすくなるように加工

進捗 level1

C++1yの新規格で関数内関数で型に応じた書き方ができなかったのが大きい.
コンパイラをclangに変えたのだが,llvmのエラーが読めん.

#include<boost/optional.hpp>
namespace KOKUU2{
namespace Match{
  template<class T> //すべてのevalに対してstd::bindで形成したstd::funtionを引数にとる
  void eval(T t){ std::cout << "default call" << std::endl;};
  template<>
  void eval<std::nullptr_t>(std::nullptr_t t){
    std::cout << "nullptr_t-type call:" << std::endl;};
  template<>
  void eval<int>(int i){
    std::cout << "int-type call:" << i << std::endl;};
  template<>
  void eval<boost::optional<int>>(boost::optional<int> x){ //ここを抽象化
    std::cout << "boost::optional<int>-type call:" << std::endl;
    std::cout << "try to get real instance..." << std::endl;
    if(x){
      eval(*x);
    }else{
      eval(nullptr);
    }
  };
};
};
int main(int argc, char const *argv[])
{
  boost::optional<int> aaa = 10;
  boost::optional<int> bbb = boost::none;
  int                  ccc = 99;
  KOKUU2::Match::eval(aaa);
  KOKUU2::Match::eval(bbb);
  KOKUU2::Match::eval(ccc);
}

...なんか,行ける気がしてきた