libcxx での C++11 type_traits ソースコードツアーメモ

## 背景

* C++11 or later の `std::enable_if` とかどういう実装になっているのかきになる.
* C++11 or later の `type_traits` の知見を増やしたい
* type_traits を自作したい

ナウでヤングな libcxx(`libc++`) のソースコードをみてみます.

http://libcxx.llvm.org/

ちなみに libcxx 全体の行数は header files で 14 万行, source files で 1.3 万行くらいです.
(gcc libstd++ は header で 4.2 万行くらい)

ソースコードは微妙に読みづらいのと, コメントが殆ど無いので, 複雑なものだとどのような理由でそのような実装になっているのかがソースコードからだけではわからないです.
(gcc 7 以降の GNU libstdc++ のほうがまだいくらかコメントあって読みやすい感があります)

あとは, libcxx のいくらかはどうみても libstc++ からパクった感がありますが, ライセンスとかいいんでしょうかね?
(`libstdc++` 自体が一部, 昔の STLPort(SGI STL. 覚えているかな!?) あたりからコピってきたのであればまあいいのかもしれません)
 
##  `std::move`

仕様では `<utility>` ですが,

https://en.cppreference.com/w/cpp/utility/move

libcxx では `type_traits` に実装されています.

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L2613

基本 `&&` に `static_cast` しているだけです.

## `std::forward`

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L2624

こちらも `static_cast`

## `std::is_same`

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L545

`__has_keyword(__is_same)` かどうかで実装が変わっていますが(`__is_same` はだいたい clang compiler 向け), コンパイラ固有のコードパスは無視して一般的なほうを見てみます.

```
template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same           : public false_type {};
template <class _Tp>            struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {};
```

template 引数が同じ型で展開できるかどうかで判定しています.

## `std::enable_if`

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L538


```
template <bool, class _Tp = void> struct _LIBCPP_TEMPLATE_VIS enable_if {};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS enable_if<true, _Tp> {typedef _Tp type;};
```

`<true, void でないなにか型>` のときに実体を作ることで実現しています.


## `std::remove_const`

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L734

```
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const            {typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const<const _Tp> {typedef _Tp type;};
```

わかりやすいですね.

## `std::is_void`

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L798


```
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_void
    : public is_same<typename remove_cv<_Tp>::type, void> {};
```

`is_same` で void と比較しています.
(`void` は型として使えるのですね)

## `std::declval`

これも仕様では `<utility>` ですが実装は `type_traits` にあります.

https://github.com/llvm/llvm-project/blob/230efefdbc1dfc025b160dec126adcb69759ba4c/libcxx/include/type_traits#L1396

ソースコードだけからはちっとも理由がわかりません.

```
// Suppress deprecation notice for volatile-qualified return type resulting
// from volatile-qualified types _Tp.
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Tp> _Tp&& __declval(int);
template <class _Tp> _Tp   __declval(long);
_LIBCPP_SUPPRESS_DEPRECATED_POP

template <class _Tp>
decltype(_VSTD::__declval<_Tp>(0))
declval() _NOEXCEPT;
```

https://stackoverflow.com/questions/56212117/understanding-declval-optimized-implementation

ありがとうございます.

でも, int と long で分けているのはなにか理由があるのですかね?(どちらも `int` でいいようなきも)

ちなみに `decltype` は C++11 言語仕様(キーワード)で, 式から型を取得します.

## その他

libcxx コード頑張って読もう!