競技プログラミング用の C++ ライブラリ
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
// macro.hpp のマクロの動作を検証する
// 入力マクロは std::cin の入力元を、出力マクロは std::cout の出力先を一時的に差し替えて検証する
// 問題の入力は使わず、すべて一致したら Hello World を出力する
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "../../src/base/macro.hpp"
bool ok = true;
void check(bool cond, const char* what) {
if (!cond) {
if (ok) std::cerr << "failed: " << what << std::endl;
ok = false;
}
}
// for 文で愚直に作った列
std::vector<ll> naive_up(ll a, ll n, ll t) {
std::vector<ll> v;
for (ll i = a; i < n; i += t) v.push_back(i);
return v;
}
std::vector<ll> naive_down(ll a, ll n, ll t) {
std::vector<ll> v;
for (ll i = n - 1; i >= a; i -= t) v.push_back(i);
return v;
}
// 出力マクロは return するので void 関数の中で使う
// after が書き換わらなければ、マクロの後ろは実行されていない
int after = 0;
void yes_upper() { YES after = 1; }
void no_upper() { NO after = 1; }
void yes_lower() { Yes after = 1; }
void no_lower() { No after = 1; }
void takahashi() { Takahashi after = 1; }
void aoki() { Aoki after = 1; }
template <class F>
std::string capture_cout(F f) {
std::ostringstream buf;
std::streambuf* old = std::cout.rdbuf(buf.rdbuf());
f();
std::cout.rdbuf(old);
return buf.str();
}
int calls = 0;
ll counted(ll x) {
calls++;
return x;
}
int main() {
// all
{
std::vector<int> v{3, 1, 2};
std::sort(all(v));
check(v == std::vector<int>({1, 2, 3}), "all");
}
// rep (1〜4 引数)
for (ll a = -3; a <= 6; a++) {
for (ll n = -3; n <= 8; n++) {
{
int cnt = 0;
rep(n) cnt++;
check(cnt == std::max<ll>(n, 0), "rep(n)");
}
{
std::vector<ll> v;
rep(i, n) v.push_back(i);
check(v == naive_up(0, n, 1), "rep(i, n)");
}
{
std::vector<ll> v;
rep(i, a, n) v.push_back(i);
check(v == naive_up(a, n, 1), "rep(i, a, n)");
}
for (ll t = 1; t <= 4; t++) {
std::vector<ll> v;
rep(i, a, n, t) v.push_back(i);
check(v == naive_up(a, n, t), "rep(i, a, n, t)");
}
{
std::vector<ll> v;
repd(i, n) v.push_back(i);
check(v == naive_down(0, n, 1), "repd(i, n)");
}
{
std::vector<ll> v;
repd(i, a, n) v.push_back(i);
check(v == naive_down(a, n, 1), "repd(i, a, n)");
}
for (ll t = 1; t <= 4; t++) {
std::vector<ll> v;
repd(i, a, n, t) v.push_back(i);
check(v == naive_down(a, n, t), "repd(i, a, n, t)");
}
}
{
std::vector<ll> v;
rrep(i, a) v.push_back(i);
check(v == naive_up(1, a + 1, 1), "rrep(i, n)");
}
{
std::vector<ll> v;
rrepd(i, a) v.push_back(i);
check(v == naive_down(1, a + 1, 1), "rrepd(i, n)");
}
}
{
// rep(n) を同じスコープで入れ子にできる (ループ変数の名前が重ならない)
int cnt = 0;
rep(3) rep(4) cnt++;
check(cnt == 12, "nested rep(n)");
// 終端と増分は最初に 1 回だけ評価される
calls = 0;
int iter = 0;
rep(i, 0, counted(5), counted(2)) iter++;
check(iter == 3 && calls == 2, "rep evaluates bounds once");
// ループ変数は long long
rep(i, 1) static_assert(std::is_same_v<decltype(i), long long>);
}
// 入力マクロ
{
std::istringstream in(
"1 -2 " // LL(a, b)
"hello world " // STR(s, t)
"7 " // IN(int, x)
"z " // CHAR(c)
"3 4 5 " // VL(v, 3)
"6 7 " // AL(arr, 2)
"1 2 3 4 5 6 " // AAL(aa, 2, 3)
"x y " // VC(vc_, 2)
"ab cd " // VS(vs_, 2)
"1 2 3 4 " // VPL(vp, 2)
"1 2 3 4 5 6 " // VAL(va, 2, 3)
"9 8 7 6 " // VVL(vv_, 2, 2)
"5 3 5 1 "); // SL(st, 4)
std::streambuf* old = std::cin.rdbuf(in.rdbuf());
LL(a, b);
STR(s, t);
IN(int, x);
CHAR(c);
VL(v, 3);
AL(arr, 2);
AAL(aa, 2, 3);
VC(vc_, 2);
VS(vs_, 2);
VPL(vp, 2);
VAL(va, 2, 3);
VVL(vv_, 2, 2);
SL(st, 4);
std::cin.rdbuf(old);
check(a == 1 && b == -2 && std::is_same_v<decltype(a), ll>, "LL");
check(s == "hello" && t == "world", "STR");
check(x == 7 && std::is_same_v<decltype(x), int>, "IN");
check(c == 'z', "CHAR");
check(v == vl({3, 4, 5}), "VL");
check(arr == al<2>{6, 7}, "AL");
check(aa == aal<2, 3>{{{1, 2, 3}, {4, 5, 6}}}, "AAL");
check(vc_ == vc({'x', 'y'}), "VC");
check(vs_ == vs({"ab", "cd"}), "VS");
check(vp == vpl({{1, 2}, {3, 4}}), "VPL");
check(va == val<3>({{1, 2, 3}, {4, 5, 6}}), "VAL");
check(vv_ == vvl({{9, 8}, {7, 6}}), "VVL");
check(st == sl({1, 3, 5}), "SL");
check(bool(in), "input stream state");
}
{
// scan を直接使う
std::istringstream in("10 abc 2.5");
std::streambuf* old = std::cin.rdbuf(in.rdbuf());
int p;
std::string q;
double r;
scan(p, q, r);
scan();
std::cin.rdbuf(old);
check(p == 10 && q == "abc" && r == 2.5, "scan");
}
// 出力マクロ (出力して return する)
after = 0;
check(capture_cout(yes_upper) == "YES\n", "YES");
check(capture_cout(no_upper) == "NO\n", "NO");
check(capture_cout(yes_lower) == "Yes\n", "Yes");
check(capture_cout(no_lower) == "No\n", "No");
check(capture_cout(takahashi) == "Takahashi\n", "Takahashi");
check(capture_cout(aoki) == "Aoki\n", "Aoki");
check(after == 0, "output macros return");
if (ok) std::cout << "Hello World" << std::endl;
}#line 1 "test/unittest/macro.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
// macro.hpp のマクロの動作を検証する
// 入力マクロは std::cin の入力元を、出力マクロは std::cout の出力先を一時的に差し替えて検証する
// 問題の入力は使わず、すべて一致したら Hello World を出力する
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#line 2 "src/base/macro.hpp"
/**
* @file macro.hpp
* @brief マクロ (rep など)
*/
#line 2 "src/base/io.hpp"
/**
* @file io.hpp
* @brief 空白区切り出力、iostreamのオーバーロード
*/
#include <array>
#line 9 "src/base/io.hpp"
#include <set>
#include <utility>
#include <tuple>
#line 13 "src/base/io.hpp"
// ネストした型 (pair<vector<int>, int> など) を扱えるように先に宣言しておく
template <typename T1, typename T2, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::pair<T1, T2>& p);
template <typename... Types, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::tuple<Types...>& p);
template <typename T, size_t N, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::array<T, N>& a);
template <typename T, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::vector<T>& v);
template <typename T1, typename T2, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::pair<T1, T2>& p);
template <typename... Types, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::tuple<Types...>& p);
template <typename T, size_t N, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::array<T, N>& a);
template <typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::vector<T>& v);
template <typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::set<T>& s);
namespace tuple_io {
template <typename Tuple, size_t I, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& read_tuple(std::basic_istream<CharT, Traits>& is, Tuple& t) {
is >> std::get<I>(t);
if constexpr (I + 1 < std::tuple_size_v<Tuple>) {
return read_tuple<Tuple, I + 1>(is, t);
}
return is;
}
template <typename Tuple, size_t I, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& write_tuple(std::basic_ostream<CharT, Traits>& os, const Tuple& t) {
os << std::get<I>(t);
if constexpr (I + 1 < std::tuple_size_v<Tuple>) {
os << CharT(' ');
return write_tuple<Tuple, I + 1>(os, t);
}
return os;
}
};
template <typename T1, typename T2, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::pair<T1, T2>& p) {
is >> p.first >> p.second;
return is;
}
template <typename... Types, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::tuple<Types...>& p) {
return tuple_io::read_tuple<std::tuple<Types...>, 0>(is, p);
}
template <typename T, size_t N, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::array<T, N>& a) {
for(auto& e : a) is >> e;
return is;
}
template <typename T, typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, std::vector<T>& v) {
for(auto& e : v) is >> e;
return is;
}
template <typename T1, typename T2, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::pair<T1, T2>& p) {
os << p.first << CharT(' ') << p.second;
return os;
}
template <typename... Types, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::tuple<Types...>& p) {
return tuple_io::write_tuple<std::tuple<Types...>, 0>(os, p);
}
template <typename T, size_t N, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::array<T, N>& a) {
for(size_t i = 0; i < N; ++i) {
if(i) os << CharT(' ');
os << a[i];
}
return os;
}
template <typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::vector<T>& v) {
for(size_t i = 0; i < v.size(); ++i) {
if(i) os << CharT(' ');
os << v[i];
}
return os;
}
template <typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::set<T>& s) {
for(auto itr = s.begin(); itr != s.end(); ++itr) {
if(itr != s.begin()) os << CharT(' ');
os << *itr;
}
return os;
}
/**
* @brief 空行出力
*/
inline void print() { std::cout << '\n'; }
/**
* @brief 出力して改行
*
* @tparam T 型
* @param x 出力する値
*/
template <typename T>
void print(const T& x) { std::cout << x << '\n'; }
/**
* @brief 空白区切りで出力して改行
*
* @tparam T 1つ目の要素の型
* @tparam Tail 2つ目以降の要素の型
* @param x 1つ目の要素
* @param tail 2つ目以降の要素
*/
template <typename T, typename... Tail>
void print(const T& x, const Tail&... tail) {
std::cout << x << ' ';
print(tail...);
}
/**
* @brief 標準エラー出力に空行出力
*/
inline void err() { std::cerr << std::endl; }
/**
* @brief 標準エラー出力に出力して改行
*
* @tparam T 型
* @param x 出力する値
*/
template <typename T>
void err(const T& x) { std::cerr << x << std::endl; }
/**
* @brief 標準エラー出力に空白区切りで出力して改行
*
* @tparam T 1つ目の要素の型
* @tparam Tail 2つ目以降の要素の型
* @param x 1つ目の要素
* @param tail 2つ目以降の要素
*/
template <typename T, typename... Tail>
void err(const T& x, const Tail&... tail) {
std::cerr << x << ' ';
err(tail...);
}
#line 2 "src/base/type_alias.hpp"
/**
* @file type_alias.hpp
* @brief 型の別名
*/
#include <bits/stdc++.h>
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template <typename T>
using vec = std::vector<T>;
template <typename T, int N>
using ary = std::array<T, N>;
using str = std::string;
using std::deque;
using std::list;
using std::map;
using std::multimap;
using std::multiset;
using std::pair;
using std::set;
using pl = pair<ll, ll>;
using pd = pair<ld, ld>;
template <typename T>
using vv = vec<vec<T>>;
template <typename T>
using vvv = vec<vec<vec<T>>>;
using vl = vec<ll>;
using vvl = vv<ll>;
using vvvl = vvv<ll>;
using vs = vec<str>;
using vc = vec<char>;
using vi = vec<int>;
using vb = vec<bool>;
template <typename T1, typename T2>
using vp = vec<pair<T1, T2>>;
using vpl = vec<pl>;
using vvpl = vv<pl>;
using vd = vec<ld>;
using vpd = vec<pd>;
template <int N>
using al = ary<ll, N>;
template <int N1, int N2>
using aal = ary<ary<ll, N2>, N1>;
template <int N>
using val = vec<al<N>>;
template <int N>
using avl = ary<vl,N>;
template <typename T>
using ml = std::map<ll, T>;
using mll = std::map<ll, ll>;
using sl = std::set<ll>;
using spl = set<pl>;
template <int N>
using sal = set<al<N>>;
template <int N>
using asl = ary<sl,N>;
template <typename T>
using heap_max = std::priority_queue<T, std::vector<T>, std::less<T>>;
template <typename T>
using heap_min = std::priority_queue<T, std::vector<T>, std::greater<T>>;
#line 10 "src/base/macro.hpp"
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define all(obj) (obj).begin(), (obj).end()
#define CONCAT_IMPL2(x, y) x##y
#define CONCAT_IMPL(x, y) CONCAT_IMPL2(x, y)
#define UNIQUE_ID(base) CONCAT_IMPL(base, __COUNTER__)
#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME
#define rep4(i, a, n, t) for (long long i = static_cast<long long>(a), i##_loop_end = static_cast<long long>(n), i##_loop_step = static_cast<long long>(t); i < i##_loop_end; i += i##_loop_step)
#define rep3(i, a, n) for (long long i = static_cast<long long>(a), i##_loop_end = static_cast<long long>(n); i < i##_loop_end; ++i)
#define rep2(i, n) rep3(i, 0, n)
#define rep1(n) rep2(UNIQUE_ID(loop_counter_), n)
#define rep(...) GET_MACRO(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define repd4(i, a, n, t) for (long long i = static_cast<long long>(n) - 1, i##_loop_end = static_cast<long long>(a), i##_loop_step = static_cast<long long>(t); i >= i##_loop_end; i -= i##_loop_step)
#define repd3(i, a, n) for (long long i = static_cast<long long>(n) - 1, i##_loop_end = static_cast<long long>(a); i >= i##_loop_end; --i)
#define repd2(i, n) repd3(i, 0, n)
#define repd(...) GET_MACRO(__VA_ARGS__, repd4, repd3, repd2)(__VA_ARGS__)
#define rrep(i, n) rep(i, 1, (n) + 1)
#define rrepd(i, n) repd(i, 1, (n) + 1)
inline void scan(){}
template<class Head,class... Tail>
inline void scan(Head&head,Tail&... tail){std::cin>>head;scan(tail...);}
#define LL(...) ll __VA_ARGS__;scan(__VA_ARGS__)
#define STR(...) str __VA_ARGS__;scan(__VA_ARGS__)
#define IN(a, x) a x; std::cin >> x;
#define CHAR(x) char x; std::cin >> x;
#define VL(a,n) vl a(n); std::cin >> a;
#define AL(a,k) al<k> a; std::cin >> a;
#define AAL(a,n,m) aal<n,m> a; std::cin >> a;
#define VC(a,n) vc a(n); std::cin >> a;
#define VS(a,n) vs a(n); std::cin >> a;
#define VPL(a,n) vpl a(n); std::cin >> a;
#define VAL(a,n,k) val<k> a(n); std::cin >> a;
#define VVL(a,n,m) vvl a(n,vl(m)); std::cin >> a;
#define SL(a,n) sl a;{VL(b,n);a=sl(all(b));}
#define NO std::cout << "NO" << std::endl; return;
#define YES std::cout << "YES" << std::endl; return;
#define No std::cout << "No" << std::endl; return;
#define Yes std::cout << "Yes" << std::endl; return;
#define Takahashi std::cout << "Takahashi" << std::endl; return;
#define Aoki std::cout << "Aoki" << std::endl; return;
#line 13 "test/unittest/macro.test.cpp"
bool ok = true;
void check(bool cond, const char* what) {
if (!cond) {
if (ok) std::cerr << "failed: " << what << std::endl;
ok = false;
}
}
// for 文で愚直に作った列
std::vector<ll> naive_up(ll a, ll n, ll t) {
std::vector<ll> v;
for (ll i = a; i < n; i += t) v.push_back(i);
return v;
}
std::vector<ll> naive_down(ll a, ll n, ll t) {
std::vector<ll> v;
for (ll i = n - 1; i >= a; i -= t) v.push_back(i);
return v;
}
// 出力マクロは return するので void 関数の中で使う
// after が書き換わらなければ、マクロの後ろは実行されていない
int after = 0;
void yes_upper() { YES after = 1; }
void no_upper() { NO after = 1; }
void yes_lower() { Yes after = 1; }
void no_lower() { No after = 1; }
void takahashi() { Takahashi after = 1; }
void aoki() { Aoki after = 1; }
template <class F>
std::string capture_cout(F f) {
std::ostringstream buf;
std::streambuf* old = std::cout.rdbuf(buf.rdbuf());
f();
std::cout.rdbuf(old);
return buf.str();
}
int calls = 0;
ll counted(ll x) {
calls++;
return x;
}
int main() {
// all
{
std::vector<int> v{3, 1, 2};
std::sort(all(v));
check(v == std::vector<int>({1, 2, 3}), "all");
}
// rep (1〜4 引数)
for (ll a = -3; a <= 6; a++) {
for (ll n = -3; n <= 8; n++) {
{
int cnt = 0;
rep(n) cnt++;
check(cnt == std::max<ll>(n, 0), "rep(n)");
}
{
std::vector<ll> v;
rep(i, n) v.push_back(i);
check(v == naive_up(0, n, 1), "rep(i, n)");
}
{
std::vector<ll> v;
rep(i, a, n) v.push_back(i);
check(v == naive_up(a, n, 1), "rep(i, a, n)");
}
for (ll t = 1; t <= 4; t++) {
std::vector<ll> v;
rep(i, a, n, t) v.push_back(i);
check(v == naive_up(a, n, t), "rep(i, a, n, t)");
}
{
std::vector<ll> v;
repd(i, n) v.push_back(i);
check(v == naive_down(0, n, 1), "repd(i, n)");
}
{
std::vector<ll> v;
repd(i, a, n) v.push_back(i);
check(v == naive_down(a, n, 1), "repd(i, a, n)");
}
for (ll t = 1; t <= 4; t++) {
std::vector<ll> v;
repd(i, a, n, t) v.push_back(i);
check(v == naive_down(a, n, t), "repd(i, a, n, t)");
}
}
{
std::vector<ll> v;
rrep(i, a) v.push_back(i);
check(v == naive_up(1, a + 1, 1), "rrep(i, n)");
}
{
std::vector<ll> v;
rrepd(i, a) v.push_back(i);
check(v == naive_down(1, a + 1, 1), "rrepd(i, n)");
}
}
{
// rep(n) を同じスコープで入れ子にできる (ループ変数の名前が重ならない)
int cnt = 0;
rep(3) rep(4) cnt++;
check(cnt == 12, "nested rep(n)");
// 終端と増分は最初に 1 回だけ評価される
calls = 0;
int iter = 0;
rep(i, 0, counted(5), counted(2)) iter++;
check(iter == 3 && calls == 2, "rep evaluates bounds once");
// ループ変数は long long
rep(i, 1) static_assert(std::is_same_v<decltype(i), long long>);
}
// 入力マクロ
{
std::istringstream in(
"1 -2 " // LL(a, b)
"hello world " // STR(s, t)
"7 " // IN(int, x)
"z " // CHAR(c)
"3 4 5 " // VL(v, 3)
"6 7 " // AL(arr, 2)
"1 2 3 4 5 6 " // AAL(aa, 2, 3)
"x y " // VC(vc_, 2)
"ab cd " // VS(vs_, 2)
"1 2 3 4 " // VPL(vp, 2)
"1 2 3 4 5 6 " // VAL(va, 2, 3)
"9 8 7 6 " // VVL(vv_, 2, 2)
"5 3 5 1 "); // SL(st, 4)
std::streambuf* old = std::cin.rdbuf(in.rdbuf());
LL(a, b);
STR(s, t);
IN(int, x);
CHAR(c);
VL(v, 3);
AL(arr, 2);
AAL(aa, 2, 3);
VC(vc_, 2);
VS(vs_, 2);
VPL(vp, 2);
VAL(va, 2, 3);
VVL(vv_, 2, 2);
SL(st, 4);
std::cin.rdbuf(old);
check(a == 1 && b == -2 && std::is_same_v<decltype(a), ll>, "LL");
check(s == "hello" && t == "world", "STR");
check(x == 7 && std::is_same_v<decltype(x), int>, "IN");
check(c == 'z', "CHAR");
check(v == vl({3, 4, 5}), "VL");
check(arr == al<2>{6, 7}, "AL");
check(aa == aal<2, 3>{{{1, 2, 3}, {4, 5, 6}}}, "AAL");
check(vc_ == vc({'x', 'y'}), "VC");
check(vs_ == vs({"ab", "cd"}), "VS");
check(vp == vpl({{1, 2}, {3, 4}}), "VPL");
check(va == val<3>({{1, 2, 3}, {4, 5, 6}}), "VAL");
check(vv_ == vvl({{9, 8}, {7, 6}}), "VVL");
check(st == sl({1, 3, 5}), "SL");
check(bool(in), "input stream state");
}
{
// scan を直接使う
std::istringstream in("10 abc 2.5");
std::streambuf* old = std::cin.rdbuf(in.rdbuf());
int p;
std::string q;
double r;
scan(p, q, r);
scan();
std::cin.rdbuf(old);
check(p == 10 && q == "abc" && r == 2.5, "scan");
}
// 出力マクロ (出力して return する)
after = 0;
check(capture_cout(yes_upper) == "YES\n", "YES");
check(capture_cout(no_upper) == "NO\n", "NO");
check(capture_cout(yes_lower) == "Yes\n", "Yes");
check(capture_cout(no_lower) == "No\n", "No");
check(capture_cout(takahashi) == "Takahashi\n", "Takahashi");
check(capture_cout(aoki) == "Aoki\n", "Aoki");
check(after == 0, "output macros return");
if (ok) std::cout << "Hello World" << std::endl;
}