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

ゆとりーなの日記

日記的な事を書いて行くと思はれる

おとついのつづき

http://d.hatena.ne.jp/nagoya313/20100924/1285341022の続きです。やっぱりstd::vector &が飛んでくるのはオーバースペックだろうと言うことで、コマンドライン引数を扱うクラスを書いてみました。既にあるかもしれないですが気にしないで行きます。

#include <boost/iterator_adaptors.hpp>

class command_line {
 public:
  struct iterator : public boost::iterator_facade<iterator, char *, boost::forward_traversal_tag> {
    iterator(int size, char **argv) : cnt_(1), size_(size), ptr_(argv) {
    }

    char *&dereference() const {
      return ptr_[cnt_ -1];
    }

    void increment() {
      if (cnt_ >= size_) {
        ptr_ = nullptr;
      } else {
        ++cnt_;
      }
    }

    bool equal(const iterator &rhs) const {
      return ptr_ == rhs.ptr_;
    }

   private:
    int cnt_;
    int size_;
    char **ptr_;
  };

  struct const_iterator : public boost::iterator_facade<const_iterator, char * const, boost::forward_traversal_tag> {
    const_iterator(int size, char **argv) : cnt_(1), size_(size), ptr_(argv) {
    }

    char * const &dereference() const {
      return ptr_[cnt_ -1];
    }

    void increment() {
      if (cnt_ >= size_) {
        ptr_ = nullptr;
      } else {
        ++cnt_;
      }
    }

    bool equal(const const_iterator &rhs) const {
      return ptr_ == rhs.ptr_;
    }

   private:
    int cnt_;
    int size_;
    char **ptr_;
  };

  command_line(int argc, char **argv) : argc_(argc), argv_(argv) {
  }

  iterator begin() {
    return iterator(argc_, argv_);
  }

  iterator end() {
    return iterator(argc_, nullptr);
  }

  const_iterator begin() const {
    return const_iterator(argc_, argv_);
  }

  const_iterator end() const {
    return const_iterator(argc_, nullptr);
  }

 private:
  int argc_;
  char **argv_;
};

取り敢えずこれで全文ですかね。constの付け方が怪しいです。かなり怪しいです。というかもっといい実装できるだろうという感じもしますし・・・。
まぁでも、

#include <iostream>
#include <string>
#include <pstade/oven/algorithm.hpp>

int main(int argc, char **argv) {
  const command_line c(argc, argv);
  command_line::const_iterator it = c.begin();
  *it = ""; // コンパイルエラー
  pstade::oven::for_each(command_line(argc, argv), [](const std::string &x) {
    std::cout << x << std::endl;
  });
  return 0;
}

的なこと出来てるし取り敢えずこれで良いかなというね、感じですね。