背景
- C++11 or later の
std::enable_if
とかどういう実装になっているのかきになる. - C++11 or later の
type_traits
の知見を増やしたい - type_traits を自作したい
ナウでヤングな libcxx(libc++
) のソースコードをみてみます.
ちなみに 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>
ですが,
libcxx では type_traits
に実装されています.
基本 &&
に static_cast
しているだけです.
std::forward
こちらも static_cast
std::is_same
__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
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
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
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
にあります.
ソースコードだけからはちっとも理由がわかりません.
// 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;
ありがとうございます.
でも, int と long で分けているのはなにか理由があるのですかね?(どちらも int
でいいようなきも)
ちなみに decltype
は C++11 言語仕様(キーワード)で, 式から型を取得します.
その他
libcxx コード頑張って読もう!