[lv5] ft_containers(0/6) はじめに

[(1/6)vectorにすすむ] https://note.com/syamashi/n/n55ee0dad207d

Q. 何をすればゴール?
A. c++98バージョンの、便利な3つのClass、 vector/stack/map を再実装します。dockerのコンテナとは関係ありません。
setはbonusですが、mapと同じ機構です。mapを赤黒木で実装しさえすれば、setへの拡張コストはとても低いです。

#include <vector> // <= この中身を自作します
#include <stack> // <= この中身を自作します
#include <map> // <= この中身を自作します
#include <set> // <= この中身を自作します

ft::vector<int> V;
ft::stack<int> S;
ft::map<int, int> M;
ft::set<int> SE;

Q. ft::?
A. 名前空間です。
using namespace std という呪文を見たことがあれば。これは「stdという名前空間にある関数を使います」という宣言です。宣言したら、以降std::を省略して記述できる呪文です。

std::vector<int> と書けば、
namespace std{
  class vector;
}
std空間のclassが呼ばれるし、

ft::vector<int> と書けば、
namespace ft{
  class vector;
}
ft空間のvectorが呼ばれます。

0. テストツールを作成します。
std::の正解出力と比較できる課題なので、diffの有無で判定できる仕組みを作ります。ft::出力の目視確認はしません。

必要になるすべてのファイルを先取りします。
/testfiles/tester.hpp

#ifndef TESTER_HPP
#define TESTER_HPP

#if TEST  // CREATE A REAL STL EXAMPLE
#include <iterator>
#include <map>
#include <set>
#include <stack>
#include <vector>
namespace ft = std;
#else
#include "../containers/map.hpp"
#include "../containers/set.hpp"
#include "../containers/stack.hpp"
#include "../containers/vector.hpp"
#include "../utils/algorithm.hpp"
#include "../utils/iterator.hpp"
#include "../utils/pair.hpp"
#include "../utils/util.hpp"
#endif

#include <stdlib.h>
#include <time.h>  // clock()

#include <algorithm>  // std::copy
#include <cmath>    // hypot set
#include <cstddef>  // size_t
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>  // cout
#include <list>      // std::list
#include <numeric>
#include <string>
#include <typeinfo>  // typeid

#define cout std::cout
#define endl std::endl
#define cerr std::cerr
#define rep(i, n) for (int i = 0; i < n; ++i)

//// tester

//// helper

#endif

Q. #if TEST
A. 定数マクロ。コンパイル時に宣言されるもので、get_next_lineでなじみがあります。
コンパイル時に -DTEST=1 でft::をstd::に置換し、std::が呼ばれ、
コンパイル時に -DTEST=0 でft::が呼ばれます。

Q. 
#define cout std::cout
#define endl std::endl
#define cerr std::cerr

A. using namespace を使ってはいけないので、頻繁に使う
cout << endl;
cerr << endl;
だけ省略表記にします。

Q. #define rep(i, n) for (int i = 0; i < n; ++i)
A. for文を省略表記にします。

/testfiles/Makefile

NAME = a.out
SRCS = $(shell find *.cpp)
OBJDIR = ./obj/
OBJS = $(SRCS:%.cpp=$(OBJDIR)%.o)

CXX = clang++ -g -O0
CFLAGS = -Wall -Werror -Wextra 

all: $(OBJDIR) $(NAME)

$(OBJDIR):
	mkdir -p obj

$(OBJDIR)%.o: %.cpp
	$(CXX) $(CFLAGS) -c -o $@ $<

$(NAME): $(OBJS)
	$(CXX) $(CFLAGS) -o $(NAME) $(OBJS)

clean:
	rm -rf $(OBJDIR)
	rm -f out_ft out_std err_ft err_std

fclean: clean
	rm -f $(NAME)

re: fclean all

Q. CXX
A. Makefileの暗黙ルールがあって、CCは.cとして認識。CXXは.cppとして認識されます。cppなので、CXXを使うのが親切。
$(OBJDIR)%.o: %.cpp
ってルールを自分で書いているので、暗黙じゃなくなり、CCでも影響ないです。

Q. CFLAGS = -Wall -Werror -Wextra
A. チュートリアル完了後に、
CFLAGS = -Wall -Werror -Wextra -std=c++98
に変更します。

ここに、便利コマンドを追加します。

test:
	$(CXX) $(CFLAGS) $(SRCS) -DTEST=0 -o $(NAME)
	@./$(NAME) > out_ft 2>err_ft
	$(CXX) $(CFLAGS) $(SRCS) -DTEST=1 -o $(NAME)
	@./$(NAME) > out_std 2>err_std
 # ret(1) cause make error.  ||: force ret(0)
	diff out_ft out_std ||:
	@echo "---ft_err---"
	@cat err_ft
	@echo "---std_err---"
	@cat err_std

test0:
	$(CXX) $(CFLAGS) $(SRCS) -DTEST=0 -o $(NAME)
	@./$(NAME) > out_ft 2>err_ft
	@cat out_ft
	@cat err_ft

test1:
	$(CXX) $(CFLAGS) $(SRCS) -DTEST=1 -o $(NAME)
	@./$(NAME) > out_std 2>err_std
	@cat out_std
	@cat err_std

Q make test
A. 
1) ft:: の標準出力をout_ftに。エラー出力をerr_ftに出力。
2) std:: の標準出力をout_stdに。エラー出力をerr_stdに出力。
3) 標準出力のdiffをとります。もしdiffがあると、エラーでMakefileが止まってしまうので、||: コマンドで強制return(0) させ、続行させます。
4) エラー出力を吐き出します。@ はターミナルに実行コマンドを表示しないオプション。

Q. tree
A. 

.
├── containers   
│   ├── map.hpp  
│   ├── set.hpp  
│   ├── stack.hpp
│   └── vector.hpp
├── testfiles
│   ├── Makefile
│   ├── main.cpp
│   ├── test_map.cpp
│   ├── test_review.cpp
│   ├── test_set.cpp
│   ├── test_stack.cpp
│   ├── test_util.cpp
│   ├── test_vector.cpp
│   └── tester.hpp
└── utils
   ├── algorithm.hpp
   ├── iterator.hpp
   ├── pair.hpp
   ├── random_access_iterator.hpp
   ├── rb_tree.hpp
   └── util.hpp

アウトラインが出そろったので、実装していきます。

[vectorチュートリアルへ]  https://note.com/syamashi/n/n55ee0dad207d


この記事が気に入ったらサポートをしてみませんか?