🧩

C++クイズ:How many operator<< overloads?

2021/09/23に公開
#include <iostream>

int main()
{
  std::cout << "<<演算子オーバーロードは全部で何種類?";
}

<<演算子オーバーロードについて。C++のストリーム出力で活躍中

<<演算子のオーバーロードってご存じですか?C++標準ライブラリのストリーム出力に使われる演算子ですよね!

文字列以外にも整数(intなど)や浮動小数点数(floatなど)のストリーム出力用に、それぞれ演算子オーバーロードが提供されているようです。C++標準ライブラリ全体では何種類のオーバーロードが存在する のでしょうか?

せいぜい 10 種類くらい?もっとたくさん 50 種類くらいでしょうか?さっそくC++バージョン別に調べてみました!!

<<演算子オーバーロードの種類は?どのヘッダで定義される!?

C++03

C++03標準ライブラリでは、28 種類のストリーム出力operator<<オーバーロードが提供されていました。

// <ostream>
template<class charT, class traits = char_traits<charT> >
class basic_ostream {
  basic_ostream<charT,traits>& operator<<(bool n);
  basic_ostream<charT,traits>& operator<<(short n);
  basic_ostream<charT,traits>& operator<<(unsigned short n);
  basic_ostream<charT,traits>& operator<<(int n);
  basic_ostream<charT,traits>& operator<<(unsigned int n);
  basic_ostream<charT,traits>& operator<<(long n);
  basic_ostream<charT,traits>& operator<<(unsigned long n);
  basic_ostream<charT,traits>& operator<<(float f);
  basic_ostream<charT,traits>& operator<<(double f);
  basic_ostream<charT,traits>& operator<<(long double f);
  basic_ostream<charT,traits>& operator<<(const void* p);
  basic_ostream<charT,traits>&
    operator<<(basic_streambuf<char_type,traits>* sb);
  basic_ostream<charT,traits>&
    operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
  basic_ostream<charT,traits>&
    operator<<(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&));
  basic_ostream<charT,traits>&
    operator<<(ios_base& (*pf)(ios_base&));
};

template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&, charT);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&, char);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, char);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, signed char);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, unsigned char);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&, const charT*);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&, const char*);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const char*);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const signed char*);
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const unsigned char*);

// <string>
template<class charT, class traits, class Allocator>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const basic_string<charT,traits,Allocator>& str);

// <complex>
template<class T, class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&, const complex<T>&);

// <bitset>
template<class charT, class traits, size_t N>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const bitset<N>& x);

おまけ:本来の「左ビットシフト」の意味でも 4 種類が提供されています。

// <bitset>
bitset<N> operator<<(size_t pos) const;

// <valarray>
valarray<T> operator<<(const valarray<T>&, const valarray<T>&);
valarray<T> operator<<(const valarray<T>&, const T&);
valarray<T> operator<<(const T&, const valarray<T>&);

C++11/14

C++11標準ライブラリでは、33 種類のストリーム出力operator<<オーバーロードが追加されました。累計だと 61 種類になります!

ちなみに、C++14標準ライブラリでの追加は行われていないようです。

// <ostream>
template<class charT, class traits = char_traits<charT> >
class basic_ostream {
  basic_ostream<charT,traits>& operator<<(long long value);
  basic_ostream<charT,traits>& operator<<(unsigned long long value);
};

template<class charT, class traits, class T>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>&& os, const T& x);

// <system_error>
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const error_code& ec);

// <memory>
template<class charT, class traits, class Y>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const shared_ptr<Y>& p);

// <regex>
template<class charT, class traits, class BiIter>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<ccharT,traits>& os, const sub_match<BiIter>& m);

// <thread>
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& out, thread::id id);

// <random>
// Random number engine requirement
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const linear_congruential_engine& e);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const mersenne_twister_engine& e);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const subtract_with_carry_engine& e);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const discard_block_engine& e);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const independent_bits_engine& e);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const shuffle_order_engine& e);
// Random number distribution requirement
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const uniform_int_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const uniform_real_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const bernoulli_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const binomial_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const negative_binomial_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const geometric_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const poisson_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const exponential_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const gamma_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const weibull_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const extreme_value_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const normal_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const lognormal_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const chi_squared_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const cauchy_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const fisher_f_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const student_t_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const discrete_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const piecewise_constant_distribution& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const piecewise_linear_distribution& d);

C++17

C++17標準ライブラリでは、3 種類のストリーム出力operator<<オーバーロードが追加されました。累計だと 64 種類になります!

// <ostream>
template<class charT, class traits = char_traits<charT> >
class basic_ostream {
  basic_ostream<charT,traits>& operator<<(nullptr_t);
};

// <string_view>
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, basic_string_view<charT,traits> str);

// <filesystem>
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const path& p);

おまけ2:本来の「左ビットシフト」の意味でも 1 種類が追加され、こちらは 5 種類目となります。

// <cstddef>
constexpr byte operator<<(byte b, IntType shift) noexcept;

C++20

最新のC++20標準ライブラリでは、42 種類のストリーム出力operator<<オーバーロードが追加されました。とうとう大台に乗り 106 種類です!!

// <memory>
template<class charT, class traits, class Y, class D>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const unique_ptr<Y,D>& p);

// <chrono>
template<class charT, class traits, class Rep, class Period>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const duration<Rep,Period>& d);

template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const sys_time<Duration>& tp);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const sys_days& dp);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const utc_time<Duration>& t);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const tai_time<Duration>& t);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const gps_time<Duration>& t);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const file_time<Duration>& tp);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const local_time<Duration>& tp);

template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const day& d);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const month& m);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year& y);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const weekday& wd);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const weekday_indexed& wdi);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const weekday_last& wdl);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const month_day& md);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const month_day_last& mdl);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const month_weekday& mwd);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const month_weekday_last& mwdl);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year_month& ym);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year_month_day& ymd);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year_month_day_last& ymdl);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year_month_weekday& ymwdi);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const year_month_weekday_last& ymwdl);
template<class charT, class traits, class Duration>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const hh_mm_ss<Duration>& hms);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const sys_info& si);
template<class charT, class traits>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const local_info& li);
template<class charT, class traits, class Duration, class TimeZonePtr>
basic_ostream<charT,traits>&
  operator<<(basic_ostream<charT,traits>& os, const zoned_time<Duration,TimeZonePtr>& t);

// <ostream>
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, wchar_t) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, char8_t) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, char16_t) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, char32_t) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, char8_t) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, char16_t) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, char32_t) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const wchar_t*) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const char8_t*) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const char16_t*) = delete;
template<class traits>
basic_ostream<char,traits>&
  operator<<(basic_ostream<char,traits>&, const char32_t*) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, const char8_t*) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, const char16_t*) = delete;
template<class traits>
basic_ostream<wchar_t,traits>&
  operator<<(basic_ostream<wchar_t,traits>&, const char32_t*) = delete;

<<演算子オーバーロードのまとめ

いかがでしたでしょうか?C++20標準ライブラリのストリーム出力operator<<オーバーロードを数えてみたら 106 種類も提供されるようです!今後もoperator<<オーバーロードの増加から目が離せませんね!!!

正直、面倒臭すぎてもうやりたくありません。 ⊂⌒~⊃。~。)⊃

Acknowledgements

https://twitter.com/vzverovich/status/1399515516218220547

Discussion