君はまだWandboxの真の実力を知らない～C++er目線で～

# Wandboxとは

https://wandbox.org

オンラインコード実行環境です。同種の他サービスと比べ、圧倒的な対応言語とコンパイラバージョン数を誇ることで、特にコンパイラのバージョンが命取りになるC++界隈では重宝されています<sup>[[要出典](https://ja.wikipedia.org/wiki/%E8%A6%81%E5%87%BA%E5%85%B8)]</sup>。また、[ideone.com](http://ideone.com)や[paiza.io](https://paiza.io)と違い、コードを書いている最中にタブを閉じてしまってもキャッシュが生きている限り作業データを取り戻せるというため、[ああああああ](http://ja.uncyclopedia.info/wiki/%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82!)とならずにすむという、細やかな気配りが見られます(意図した挙動なのかな？)。

@melpon 氏、@kikairoya 氏はじめ、[数人が](https://github.com/melpon/wandbox/graphs/contributors)開発に携わっています。

最新のGCCやClangが使えるため、[煩雑極まりないコンパイラのHEAD(開発中の最新版)のビルドを自分でやらずに利用できるという喜びの声もあります](https://cpplover.blogspot.jp/2013/12/wandbox-vimc14.html)。

あくまで個人でやっているサービスのため、先日資金難に陥ったための[スポンサー募集](https://twitter.com/melponn/status/841299042478899200)[をかけていました](https://twitter.com/melponn/status/841299235785981952)。

[Wandboxのスポンサー募集](https://gist.github.com/melpon/8f5d7a8e991ed466d09cf887bd8d92ce)

TwitterのTLを追っていなかった人には突如としてWandboxの左側にCorporate Sponsors:とPersonal Sponsors:が現れて驚いたのではないでしょうか。

[当座](https://twitter.com/melponn/status/841436806600056832)十分な資金が集まったらしく、サービスは継続するらしいです。ついでにSSL接続になりました。継続するのだからどんどんどん活用するべきでしょう(typoにあらず)。

# 注意

以降スクリーンショットは2017/4/15現在のUIです。UIは変更になる可能性は・・・きっとあるんじゃないかなぁ、しらないけど。

# まずはどんなサーバーなのか見てみよう

せっかくbash scriptを動かせるのですからまずやることは

```bash
cat /proc/cpuinfo
```

でしょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/5e1eceb0-2b19-9346-3ceb-42354de48928.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/94177/1dbb1b2c-6d7c-77a0-42de-1c4bfaa059d7.png)

Languagesは　Bash script、バージョンは一つしかないのでbash 4.3.46(1)-releas を選びました。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/44a7cb9d-2eef-74db-2a59-dd2a17711dc8.png)

コードを書いて、「Run」をクリックするか<kbd>Ctrl</kbd>+<kbd>Enter</kbd>で実行されます。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/23f3f6f2-66b5-03f3-3da8-9ba848446739.png)

Shere This Codeを押すとURLが割り振られて、公開されます。公開する気もないのに押すのはいいことではない気がします。

結果: https://wandbox.org/permlink/2WNGw7YDL28xnt56

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">この記事でyumetodoさんが「SIMDが使えるオンライン環境としては」云々とありましたので、<br>てっきりwandboxではSIMDできないのかと思ってテストコードを投げたら普通に使えました……ｗ<a href="https://t.co/WwrfuhIlmL">https://t.co/WwrfuhIlmL</a></p>&mdash; YSR@冴えカノ2期視聴勢 (@YSRKEN) <a href="https://twitter.com/YSRKEN/status/850598444364308480">2017年4月8日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">で、wandbox相手に「cat /proc/cpuinfo」してみたところ、<br>「Intel Xeon E312xx (Sandy Bridge)を1コア×3ソケット分提供するゾ」と返されたのでびっくり。<br>AVX2は使えないもののAVXは使用可能だと分かりました</p>&mdash; YSR@冴えカノ2期視聴勢 (@YSRKEN) <a href="https://twitter.com/YSRKEN/status/850599448229036032">2017年4月8日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">これは <a href="https://twitter.com/melponn">@melponn</a> 氏に焼肉をみんながおごったからか？(前からAVX使えてたならごめんなさい、知りませんでした) <a href="https://t.co/B93j499T7K">https://t.co/B93j499T7K</a></p>&mdash; yumetodo-C++erだけど化学科 (@yumetodo) <a href="https://twitter.com/yumetodo/status/850608816429293569">2017年4月8日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/YSRKEN">@YSRKEN</a> <a href="https://twitter.com/yumetodo">@yumetodo</a> コードを実行してるさくらVPSのサーバは結構最近借りたものなので、それのおかげの可能性はあるかも</p>&mdash; めるぽん(Wandboxの中の人) (@melponn) <a href="https://twitter.com/melponn/status/850646457019359232">2017年4月8日</a></blockquote>

はい、どうやらIntelのCPUで、SIMDもAVXまで使えるようです。強い。

# 普通にC++のコードをコンパイルしよう

さっきも見たように膨大な数のLanguagesとVersionが選べますが、そろそろタイトル詐欺にならないようにC++のコードをコンパイルしていきましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/feb9a32e-2167-0315-c83a-9f37f0120a51.png)

C++の場合の設定項目はこんな感じです。詳細は後述します。

```cpp
#include <iostream>
int main()
{
    std::cout << "arikitari_na_world!" << std::endl;
}
```

https://wandbox.org/permlink/uC4q49JL9Qps6opo

# File I/Oもやってみよう

```plain:a.txt
arikitari
na
world!

```

のようなファイルが有ったとしてそれを全部読み出して標準出力に書き出すコードは

```cpp
#include <fstream>
#include <iostream>
int main()
{
    std::ifstream in("a.txt");
    std::cout << in.rdbuf();
}
```

のように書けます。ちゃんとファイルを開けるので結果はもちろん

```plain:実行結果
arikitari
na
world!
```

になります。

https://wandbox.org/permlink/q1XLmeuKvvOMJneb

# Boostを使ってみよう

Boostでまあもっとも手軽なのといえば``boost::optinal``だと思うので、使ってみましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/518791ca-3993-4a15-6ead-8663113af764.png)

図のようにBoostのバージョンが選べます。基本的には一番新しいのを使っとけばいいでしょう。

```cpp
#include <iostream>
#include <boost/optional.hpp>
boost::optional<int> f(int n)
{
    return { n };
}

int main()
{
    const auto n = f(23);
    if(n) std::cout << *n << std::endl;
}
```

https://wandbox.org/permlink/y1xbcwppoZgo6de2

無事にコンパイルして実行できました。

# Sproutを使ってみみよう

SproutとはC++11で追加されC++14で強化されたconstexprを始めとする機能を使ってコンパイル時に様々な処理を行えるようにすることを目的としたライブラリです。
https://github.com/bolero-MURAKAMI/Sprout
[@bolero_MURAKAMI](https://twitter.com/bolero_MURAKAMI)氏が開発しています。

使うためには
![image](https://qiita-image-store.s3.amazonaws.com/0/94177/88f8692a-8613-3e09-da2d-281e12832448.png)
Sproutにチェックを入れるだけで良いです、ほぼ最新のSproutが常に使えます。

さて、Sproutにもoptionalがあります。このoptionalはboostのとは違って、範囲を持っているのでRange-based forでつかえる便利なやつなので使ってみましょう。

```cpp
#include <iostream>
#include <sprout/optional.hpp>
sprout::optional<int> f(int n)
{
    return { n };
}

int main()
{
    const auto n = f(23);
    for(int i : n) std::cout << i << std::endl;
}
```

https://wandbox.org/permlink/ghgQZDni5RRrR80i

# SIMDなコードも書いてみよう

白状しよう。私はまともに高速なSIMDを使ったコードもかけない情弱だと。
ところが適当な題材がつい先日出てきました。
[SIMD intrinsicでチェックディジットを計算してみる その2](http://qiita.com/YSRKEN/items/17097b26ddf0754c5d34)
これだ。マイナンバーの最後の桁はチェックデジットなのですが、これを高速に導出するコードをサンプルに使います。
[@MaverickTse](https://twitter.com/MaverickTse), [@mtfmk](https://twitter.com/mtfmk), @YSRKEN 氏の格闘の結果生まれたコードです。

ベンチマーク部分のコードもあるからちと長い。

```cpp
#include <iostream>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <array>
#include <random>
#include <chrono>
#include <random>
#include <vector>
#include <string>
#include <cstdint>
#include <algorithm>
#include <stdexcept>
#include <unordered_set>
#include <functional>
#include <limits>
#include <cstring>
#include <cctype>
#include <emmintrin.h>
#include <immintrin.h>
#define SPROUT_CONFIG_DISABLE_VARIABLE_TEMPLATES 1
#if defined(_MSC_VER) && !defined(__c2__)
#	pragma warning(disable: 5030)//警告	C5030	属性 'gnu::unused' は認識されません
#	if 191025017 <= _MSC_FULL_VER
#		define SPROUT_CONFIG_FORCE_CXX14_CONSTEXPR 1
#	endif
#endif
#include <sprout/array.hpp>
std::mt19937 create_rand_engine() {
	std::random_device rnd;
	std::vector<std::uint_least32_t> v(10);// 初期化用ベクタ
	std::generate(v.begin(), v.end(), std::ref(rnd));// ベクタの初期化
	std::seed_seq seed(v.begin(), v.end());
	return std::mt19937(seed);// 乱数エンジン
}
std::string generate_input() {
	static auto mt = create_rand_engine();
	static std::uniform_int_distribution<std::uint16_t> dist(0u, 9u);
	std::string re;
	re.resize(11);
	std::generate(re.begin(), re.end(), []() -> char {
		return char('0' + dist(mt));
	});
	return re;
}
using calc_check_digit_f = std::uint8_t(*)(const std::string&);
struct test_result {
	std::string test_case;
	std::uint8_t expected;
	std::uint8_t actual;
};
std::ostream& operator<<(std::ostream& os, const test_result& t) {
	os << "testcase:" << t.test_case << ": expected(" << std::uint16_t(t.expected) << ") actual(" << std::uint16_t(t.actual) << ')';
	return os;
}
auto test(calc_check_digit_f f) {
	static const std::pair<std::string, std::uint8_t> testcase[] = {
		{ "12345678901", 8 },
		{ "56661137362", 0 },
		{ "61671451309", 6 },
		{ "66383747390", 9 },
		{ "08065140466", 9 },
		{ "15473503678", 2 },
		{ "40113376378", 8 },
		{ "12226480680", 0 },
		{ "82046894873", 4 },
		{ "48880517043", 6 },
		{ "97816786786", 3 }
	};
	std::vector<test_result> fail;
	fail.reserve(sizeof(testcase) / sizeof(*testcase));
	for (auto&& t : testcase) {
		try {
			const auto re = f(t.first);
			if (re != t.second) fail.push_back({ t.first, t.second, re });
		}
		catch (...) {
			fail.push_back({ t.first, t.second, std::uint8_t(0xff) });
		}
	}
	return fail;
}
std::chrono::nanoseconds bench(const char* func_name, calc_check_digit_f f, const std::vector<std::string>& inputs) {
	namespace ch = std::chrono;
	using hc = ch::high_resolution_clock;
	const auto test_re = test(f);
	auto v2s = [](const std::vector<test_result>& a) {
		std::stringstream ss;
		for (auto&& t : a) ss << t << std::endl;
		return ss.str();
	};
	const auto t0 = hc::now();
	[[gnu::unused]] std::uint8_t dst;
	for (auto&& i : inputs) dst = f(i);
	const auto t1 = hc::now();
	const auto t = t1 - t0;
	std::cout
		<< func_name << " : test::" << (test_re.empty() ? "pass:" : "fail:")
		<< ch::duration_cast<ch::milliseconds>(t).count() << "[ms] ("
		<< ch::duration_cast<ch::nanoseconds>(t).count() << "[ns])" << std::endl;
	if(!test_re.empty()) std::cout << v2s(test_re) << std::endl;
	return ch::duration_cast<ch::nanoseconds>(t);
}
SPROUT_CXX14_CONSTEXPR sprout::array<std::uint8_t, 1000> make_mod_table_ysr() {
	sprout::array<std::uint8_t, 1000> re{};
	for (size_t i = 0; i < 1000; ++i) {
		size_t mod = i % 11;
		re[i] = static_cast<std::uint8_t>(mod <= 1 ? 0 : 11 - mod);
	}
	return re;
}

static inline bool validate(const __m128i& x)
{
	__m128i t = _mm_sub_epi8(x, _mm_min_epu8(x, _mm_set1_epi8(9)));
	return _mm_test_all_zeros(t, _mm_setr_epi32(-1, -1, 0x00FFFFFF, 0)) == 1;
}
uint8_t calc_check_digit_mtfmk_ysrken(const std::string& str) noexcept
{
	static SPROUT_CXX14_CONSTEXPR auto mod_table = make_mod_table_ysr();
	if (str.size() != 11) {
		return 0xFE;
	}

	__m128i p_n = _mm_loadu_si128(reinterpret_cast<const __m128i*>(str.c_str()));
	p_n = _mm_sub_epi8(p_n, _mm_set1_epi8('0'));
	if (!validate(p_n)) {
		return 0xFF;
	}

	__m128i sum = _mm_maddubs_epi16(p_n, _mm_setr_epi8(6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2, 0, 0, 0, 0, 0));
	sum = _mm_sad_epu8(sum, _mm_setzero_si128());
	sum = _mm_add_epi32(sum, _mm_srli_si128(sum, 8));
	return mod_table[_mm_cvtsi128_si32(sum)];
}

int main() {
	SPROUT_CONSTEXPR int test_times = 10000000;
	try {
		std::cout << "generating inputs..." << std::flush;
		std::vector<std::string> inputs(test_times);
		std::generate(inputs.begin(), inputs.end(), []() { return generate_input(); });
		std::cout
			<< "done." << std::endl
			<< "start benchmark mark:" << std::endl;

		bench("calc_check_digit_mtfmk_ysrken", calc_check_digit_mtfmk_ysrken, inputs);
		std::cout << std::endl << "benchmark finish!" << std::endl;
	}
	catch (const std::exception& er) {
		std::cerr << er.what() << std::endl;
	}
}
```

https://wandbox.org/permlink/aORacqpNCuGHDj4Q

冒頭も書いたように、SIMDなコードがWandboxで使えるようになったのは割と最近なので感慨深いですね。当たり前ですがAVX2なコードを書こうとするとヘッダーファイルがなくて詰みますん。

コンパイル時に剰余計算とかをやってしまって配列に保存しておく処理がありますが(``make_mod_table_ysr``)、これは``std::array``だと``operator[]``がconstexprではないのでやむなくsproutを使っています。

# ヘッダーファイルを追加してみよう

その昔Wandboxは一つのファイルしか扱えなかったですが、だいぶ前から複数のファイルを扱うことができるようになっています。

何に役立つかというと、ヘッダーオンリーライブラリを利用できるようになります。
ここでは
[C++でPStade.Oven(pipeline)風味なstringのsplitを作ってみた](http://qiita.com/yumetodo/items/bf2bc5c1d49d5aec3efa)
で紹介した文字列分割ライブラリを使ってみましょう(ステマ)

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/80b43baf-e5c4-07bd-b02a-05b7a18e7394.png)
まずは普通にコードを書きます。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/ced80ef2-f2f7-d4f1-d7cf-e24e6370ea68.png)
そうしたらヘッダーファイルを追加したいので、この＋ボタンを押します。

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/cb1c1428-6674-6be2-c194-421df65333ec.png)
ファイルが作られたのでクリックします

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/f5139cd8-8999-3a89-9e27-207707250e0d.png)
追加したいヘッダーファイルの中身を書きます

![image](https://qiita-image-store.s3.amazonaws.com/0/94177/78788896-2d83-aa23-42c0-6d47bee22058.png)
タブをダブルクリックするとファイル名を編集できるので、書き換えましょう。

あとは普通にオプションいじって実行するだけです。

https://wandbox.org/permlink/gnDQnaJJOcH44hod

# ファイル名編集部分でディレクトリも作れる

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> <a href="https://twitter.com/kariya_mitsuru">@kariya_mitsuru</a> <a href="https://twitter.com/srz_zumix">@srz_zumix</a> あれ、一応タブのファイル名は a/b/c.hpp とかできるようにしてますけどそういうのではなく？</p>&mdash; めるぽん(Wandboxの中の人) (@melponn) <a href="https://twitter.com/melponn/status/851458915581607936">2017年4月10日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> <a href="https://twitter.com/melponn">@melponn</a> <a href="https://twitter.com/kariya_mitsuru">@kariya_mitsuru</a> <a href="https://twitter.com/srz_zumix">@srz_zumix</a> ディレクトリ作れるのでは<a href="https://t.co/qwHsrlLsfj">https://t.co/qwHsrlLsfj</a></p>&mdash; 白山風露 (@kazatsuyu) <a href="https://twitter.com/kazatsuyu/status/851458968668876802">2017年4月10日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> <a href="https://twitter.com/melponn">@melponn</a> <a href="https://twitter.com/kariya_mitsuru">@kariya_mitsuru</a> <a href="https://twitter.com/srz_zumix">@srz_zumix</a> URL間違えた <a href="https://t.co/fLbXxCCfft">https://t.co/fLbXxCCfft</a></p>&mdash; 白山風露 (@kazatsuyu) <a href="https://twitter.com/kazatsuyu/status/851459270742687744">2017年4月10日</a></blockquote>

https://wandbox.org/permlink/GH47JTHmSoyyIlGo

のように、ファイル名編集のところで``/``を書くとディレクトリが作れるようです。ただし``../a.txt``とかはかけないです。

# 複数の翻訳単位をコンパイルしてみよう

C/C++では普通ヘッダーファイルとソースファイルがあり、ソースファイルをそれぞれコンパイルしてリンクし、実行ファイルを作ります。つまりソースファイルごとに翻訳が行われるのでそれぞれを翻訳単位と言います(常識)。
ここまですべてソースファイルが一つ、つまり翻訳単位が一つのプログラムばかり取り上げてきました。

ではどうすれば複数の翻訳単位をコンパイルすればいいのでしょうか？

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> 多分、匿名名前空間の方が、staticでは対応しきれないパターンのために用意された感じではないでしょうか。<br>名前空間内のstatic関数は、匿名名前空間で定義した場合とほぼ同じ動作をします。<a href="https://t.co/KV035mCVne">https://t.co/KV035mCVne</a></p>&mdash; 白山風露 (@kazatsuyu) <a href="https://twitter.com/kazatsuyu/status/787529961141710848">2016年10月16日</a></blockquote>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/kazatsuyu">@kazatsuyu</a> ほう、ますますstatic/extern/inlineまわりわかんねぇ・・・。<br><br>ところでwandboxで複数の翻訳単位作る方法あったのか・・・<a href="https://twitter.com/srz_zumix">@srz_zumix</a> 氏のiuwandboxつかっててヘッダーオンリーなものしか使えないイメージだった</p>&mdash; yumetodo-C++erだけど化学科 (@yumetodo) <a href="https://twitter.com/yumetodo/status/787531223589543936">2016年10月16日</a></blockquote>

@kazatsuyu 氏の情報提供によりその方法が明らかになりました。

ここで出番になるのが``Compiler options:``です。

1. main関数があるソースファイルを一番最初のタブに貼り付ける([一番最初(prog.cc)にないとリンカエラーになります](https://github.com/srz-zumix/iutest/issues/13#issuecomment-287239197))
2. それ以外のヘッダーファイル、ソースファイルを他のタブに貼り付ける(ファイル名をつけるのをお忘れなく)
3. ソースファイルを``Compiler options:``にすべて**改行区切りで**指定する

例えば

```cpp:prog.cc
#include <iostream>
#include "a.hpp"

int main() {
    std::cout << (f == g);
}
```

```cpp:a.hpp
static inline void f(){}

extern void(*g)();
```

```cpp:a.cpp
#include "a.hpp"

void (*g)() =f;
```

のようにあったときは

```plain:Compiler_options
a.cpp
```

のように指定すると

https://wandbox.org/permlink/GSuuSwIOk4HdGJPg

のように実行できます。

注意点としては

- ``Compiler options:``に複数のことを書くときは常に改行区切り
- クオートされて渡されるので余計なスペースは入れない

でしょうか。

なお、中の人こと @melpon 氏の反応がこちら。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> <a href="https://twitter.com/kariya_mitsuru">@kariya_mitsuru</a> というかコンパイルオプションにファイル名入れたら使えるの盲点でした。確かにこれでいける…</p>&mdash; めるぽん(Wandboxの中の人) (@melponn) <a href="https://twitter.com/melponn/status/851457823103868928">2017年4月10日</a></blockquote>

# OpenSSLを使ってみよう

WandboxにはOpenSSLもあるので使ってみましょう。と言ってもネットワーク通信は死んでいるようなので実行はできませんが、コンパイルはできます。

使えるバージョンは

```bash
ls /opt/wandbox/ | grep openssl
```

すればわかりますが、``1.1.0e``はどうもヘッダーがぶっ壊れているので(Wandboxのせいではなく)``1.0.2k``を今回は使います。
https://wandbox.org/permlink/aZi1sLFmojdd0vbX

で、OpenSSLを直叩きとかできる気がしないので、Boost.asio.sslを使うコードをコンパイルしてみましょう。
https://github.com/yumetodo/boost_asio_ssl_file_dl_test

``Compiler options:``に大量にいろいろ指定することになります。pkgconf?今回の場合あってもさして簡単にならないよ(使えるのか知らない)

まず、OpenSSLがある場所をコンパイラに伝えるために

```
-I/opt/wandbox/openssl-1.0.2k/include
-L/opt/wandbox/openssl-1.0.2k/lib
```

が必要です。それから先に複数の翻訳単位をコンパイルする方法で述べたように、今回も複数の翻訳単位があるので

```
downloader.cpp
downloader_impl.cpp
```

を指定します。あとはリンクするものですね。

```
-lssl
-lcrypto
-ldl
```

``-lssl``と``-lcrypto``は[順番を間違えるとリンクエラーになります](https://ubuntuforums.org/archive/index.php/t-985136.html)ね

すべて合わせると

```plain:Compiler_options
-I/opt/wandbox/openssl-1.0.2k/include
-L/opt/wandbox/openssl-1.0.2k/lib
downloader.cpp
downloader_impl.cpp
-lssl
-lcrypto
-ldl
```

こうなりますね。実行結果は
https://wandbox.org/permlink/uK0Z9eWfFlX3WGUN
です。予想通り実行時に例外はいて死にます。

なんでかというと、セキュリティのために、そもそもソケットが作れないからです。

試しにsocktでpingを作っている適当なプログラムを走らせてみると
http://www.geekpage.jp/programming/linux-network/simple-ping.php

https://wandbox.org/permlink/whHEfqASfbAb76BU

```
socket: Operation not permitted
```

と言われます。ソケットすら開けねぇから何もできんですね。

# sqlite3を使ってみよう

sqliteも使えるみたいですね。[公式サンプル](https://www.tutorialspoint.com/sqlite/sqlite_c_cpp.htm)のCreate a Tableの項を動かしてみましょう。

```plain:Compiler_options
-I/opt/wandbox/sqlite-3.17.0/include
-L/opt/wandbox/sqlite-3.17.0/lib
-lsqlite3
```

まあCompiler　optionsに書くことはさっきとそう変わらないですね。

https://wandbox.org/permlink/pBHLJvGHqTMzSVao

無事実行できました。

# Range-v3を使ってみよう

Range-v3が何かについては
[[c++,boost] Eric Niebler's range 3.0の基本設計思想](http://qiita.com/kktk-KO/items/41e85427864365dd88fd)
に丸投げして、公式サンプルを動かしてみましょう。カレンダーのやつはコンパイル中にメモリーが足りなくなったのでフィボナッチ数列で。
https://github.com/ericniebler/range-v3/blob/963ac2617d7593b120df34e38d1916b31a878757/example/fibonacci.cpp

https://wandbox.org/permlink/beO0B0Z22G46syxg

# Bash scriptから任意バージョンのコンパイラでC++のコードをコンパイルしよう

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Wandbox、複数の翻訳単位っていうかbash動くから色々やれる <a href="https://t.co/mKwxmBLe7m">https://t.co/mKwxmBLe7m</a></p>&mdash; いぐにすさん (@ignis_fatuus) <a href="https://twitter.com/ignis_fatuus/status/851679644680019969">2017年4月11日</a></blockquote>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/ignis_fatuus">@ignis_fatuus</a> なおGCCのバージョン</p>&mdash; yumetodo-C++erだけど化学科 (@yumetodo) <a href="https://twitter.com/yumetodo/status/851686267821608960">2017年4月11日</a></blockquote>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> 色々やれるといったはずだ <a href="https://t.co/yYMannoRE9">https://t.co/yYMannoRE9</a></p>&mdash; いぐにすさん (@ignis_fatuus) <a href="https://twitter.com/ignis_fatuus/status/851688055077429248">2017年4月11日</a></blockquote>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/ignis_fatuus">@ignis_fatuus</a> /opt/wandbox/<br>そこにあるのか、ずっとどこかわからず探し回ってた</p>&mdash; yumetodo-C++erだけど化学科 (@yumetodo) <a href="https://twitter.com/yumetodo/status/851690052539228160">2017年4月11日</a></blockquote>

@ignis_fatuus 氏から情報提供頂いたので検証してきましょう。

まず

```bash
ls /opt/wandbox | grep gcc
```

の結果を見てみると

```
gcc-4.4.7
gcc-4.5.4
gcc-4.6.4
gcc-4.7.3
gcc-4.7.4
gcc-4.8.1
gcc-4.8.2
gcc-4.8.3
gcc-4.8.4
gcc-4.8.5
gcc-4.9.0
gcc-4.9.1
gcc-4.9.2
gcc-4.9.3
gcc-5.1.0
gcc-5.2.0
gcc-5.3.0
gcc-5.4.0
gcc-6.1.0
gcc-6.2.0
gcc-6.3.0
gcc-head
```

のようになります。

https://wandbox.org/permlink/l55cQpsy0SqqUD3r

次に

```bash
ls -l /opt/wandbox/gcc-6.3.0/bin
```

してみると

```
total 42416
-rwxr-xr-x 1 root root 4544016 Jan 27 23:26 c++
-rwxr-xr-x 1 root root 4537480 Jan 27 23:26 cpp
-rwxr-xr-x 1 root root 4544016 Jan 27 23:26 g++
-rwxr-xr-x 1 root root 4533168 Jan 27 23:26 gcc
-rwxr-xr-x 1 root root  146248 Jan 27 23:26 gcc-ar
-rwxr-xr-x 1 root root  146168 Jan 27 23:26 gcc-nm
-rwxr-xr-x 1 root root  146184 Jan 27 23:26 gcc-ranlib
-rwxr-xr-x 1 root root 3133744 Jan 27 23:26 gcov
-rwxr-xr-x 1 root root 3080944 Jan 27 23:26 gcov-tool
-rwxr-xr-x 1 root root 4544016 Jan 27 23:26 x86_64-pc-linux-gnu-c++
-rwxr-xr-x 1 root root 4544016 Jan 27 23:26 x86_64-pc-linux-gnu-g++
-rwxr-xr-x 1 root root 4533168 Jan 27 23:26 x86_64-pc-linux-gnu-gcc
-rwxr-xr-x 1 root root 4533168 Jan 27 23:26 x86_64-pc-linux-gnu-gcc-6.3.0
-rwxr-xr-x 1 root root  146248 Jan 27 23:26 x86_64-pc-linux-gnu-gcc-ar
-rwxr-xr-x 1 root root  146168 Jan 27 23:26 x86_64-pc-linux-gnu-gcc-nm
-rwxr-xr-x 1 root root  146184 Jan 27 23:26 x86_64-pc-linux-gnu-gcc-ranlib
```

おお？

https://wandbox.org/permlink/p8PypUhINVks1IVk

ならば、

```bash
/opt/wandbox/gcc-6.3.0/bin/gcc --version
```

の結果は・・・？

```
gcc (GCC) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

おお！！

https://wandbox.org/permlink/cgD9MvAdrggqSBsf

つまり

```bash:prog.sh
/opt/wandbox/gcc-6.3.0/bin/g++ --version
/opt/wandbox/gcc-6.3.0/bin/g++ a.cpp b.cpp
./a.out
```

```cpp:a.cpp
#include<iostream>
#include"b.h"
int main() {
    std::cout << "Hello" << std::endl;
    b();
}
```

```cpp:b.h
void b(void);
```

```cpp:b.cpp
#include<iostream>
void b(void) {
    std::cout << __FILE__ << std::endl;
}
```

とかするとコンパイルして実行できてしまう！

GNUmakeとかninjaとかCMakeとかはないですが、bash scriptはあるので文字通りなんでもできちゃいますね！

唯一の難点はSyntax highlightが仕事しないことでしょうか。

# Wandbox APIを利用する

Wandbox APIに特定フォーマットJSONを投げつけることでビルドして実行結果を返してくれます。

## 各種エディタからWandboxを使う

vim
https://github.com/rhysd/wandbox-vim

emacs
https://github.com/kosh04/emacs-wandbox

Visual Studio Code
https://github.com/wraith13/wandbox-vscode

なんかいろいろあります。詳細は割愛

## iuwandbox.py

まあまずiutestという [@srz-zumix](https://twitter.com/srz_zumix)氏が開発しているC++のテストフレームワークがあるわけですが、
https://github.com/srz-zumix/iutest
そのツールとして、iuwandbox.pyがあります。

導入はかんたんです

1. python3かpython2とGNUMakeが動く環境を用意します。Windowsだったらmsys2とか？
2. gitとかでiutestを落としてくる
3. ``cd <iutestのあるパス>``
4. ``make -C tools/fused``

使ってみましょう。使い方は
http://srz-zumix.github.io/iutest/
に記述があります。

- 複数ヘッダーファイル対応(相対パス自動解決)
- 複数翻訳単位対応(暫定)
- boost, sprout対応

となかなかポテンシャル高いです。

## Cranberries Build Tool

C, C++, Go、Rubyのみ対応したWandboxをコマンドラインから叩くツール。こっちはgolangで作られている。

[GoでWandboxにコードを送って実行結果を見る - Qiita](https://qiita.com/_EnumHack/items/d1d0fb7e6782c06f84ff)

導入は難しくない。

### マニュアルインストール

[リリースページ](https://github.com/LoliGothick/cbt/releases)からダウンロードして自分でインストールする。

### go getを使って導入

1. [Chocolatey](https://chocolatey.org/)などでgolangを導入する(go-1.9以上が必要)

2. ```go get github.com/LoliGothick/cbt```

3. ```dep ensure```（推奨）

4. ```go install github.com/LoliGothick/cbt```

5. `$GOPATH/bin`にパスを通す。Windowsだとデフォルトなら`$env:HOME/go/bin`



使い方は例えば

```
cbt wandbox cpp --std c++14 -w .\vector_growth_test.cpp
```

とかする。

# 余談:Share This Codeを取り消せるか

**取り消せません**

サーバーのDBにどんどんゴミが溜まっていくんじゃないかという気がしますが

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> <a href="https://twitter.com/TheorideTech">@TheorideTech</a> データは残りますが、こっちとしては大したサイズでも無いので全く気にならないですね。ユーザ認証は、そんなに便利でも無いよなーとか思ったりして手を出しにくかったり</p>&mdash; めるぽん(Wandboxの中の人) (@melponn) <a href="https://twitter.com/melponn/status/853076255012343809">2017年4月15日</a></blockquote>

とのことなので常識的な範疇で使っていれば問題はないんでしょう。

# 感想

- Wandboxのポテンシャル高い
- ``/opt/wandbox``にだいたいなんでもあるのでBash Scriptでゴリ押せる
- iuwandboxのポテンシャルも高い

# 追記

ユーザー認証機能が追加された。
[WandboxにGithubを利用したユーザー認証が来た](http://qiita.com/yumetodo/items/76277399df7057f6d4d5)

# License

[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)

<a href="https://commons.wikimedia.org/wiki/File:CC-BY_icon.svg#/media/File:CC-BY_icon.svg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/CC-BY_icon.svg/1200px-CC-BY_icon.svg.png" alt="CC-BY icon.svg" width="88px"></a>