追記(2017/04/02)
もっといい感じでブログに書き直したのでそっち参照してください。
Rustとかgraphvizとかにも対応しました。
追記(2016/03/13)
#if 0
g++ -std=c++11 "$0" && ./a.out
exit
#endif
これで十分だった。なんで #if 0
を捨てようと頑張ってたんだろう……
というわけで、この記事には謎の無駄があるので、それを踏まえてどうぞ。
TL;DR
先頭に
///bin/true<<//
#if 0
//
g++ -std=c++11 "$0" && ./a.out
exit
#endif
を入れる。
実行は、単にシェルに渡してやればよい。
$ sh foo.cpp
以上。
なお、 g++
の部分には #
で始まる行以外なら何でも書けるし、複数行でも問題ない。
実行例
///bin/true<<//
#if 0
//
g++ -std=c++11 "$0" && ./a.out
exit
#endif
// put C++ source below.
#include<iostream>
int main(void)
{
std::cout << "Hello world" << std::endl;
return 0;
}
$ sh foo.cpp
Hello world
$
解説
大雑把に言えばこういうことである。
-
g++
を起動する、シェルスクリプトとしてのソースが存在する。- これはC++から見てコメントである。
- C++としてのソースが存在する。
- これはシェルスクリプト部分の終了後に置いてある。
///bin/true<<//
/bin/true
とヒアドキュメントを使って、特定部分のテキストをシェルから無視させる。
この部分にC++コードを入れる。
同時に、この行は //
で始まるから、行コメントとしてC++コンパイラからは無視される。
E10) Why does
cd //
leave$PWD
as//
?POSIX.2, in its description of
cd
, says that three or more leading
slashes may be replaced with a single slash when canonicalizing the
current working directory.This is, I presume, for historical compatibility. Certain versions of
Unix, and early network file systems, used paths of the form
//hostname/path
to access 'path' on server 'hostname'.
(Bash FAQ より引用)
上に引用したlinux - what is path //, how is it different from / - Stack Overflowによると、POSIX.2 では、パスの先頭の3つ以上連続するスラッシュはひとつに置換されるらしいので、これを利用すると ///bin/true
は /bin/true
として扱われる。
/bin/true
は、リターンコード 0
を返すだけのシンプルなプログラムだ。
何も出力を行わないので、入力を食わせて無視させるには丁度良い。
<<//
はヒアドキュメントである。
説明するまでもないが、 //
という文字列だけの行の直前までを標準入力に流し、 //
の行そのものは飛ばされる。
#if 0
言わずと知れた、C/C++のプリプロセッサを利用したコメント。
/* */
と違ってネスト可能なので一部用途で重宝される。
同時に、この行そのものは #
から始まるため、シェルにもコメント扱いされる。
ここから #endif
までがC++としては無視されるので、そこにシェルスクリプト本体を書く。
シェルスクリプト部
べつにコマンドは g++
でなくとも何でも良い。
wc
で行数を数えてもいいし、なんだったら cppcheck
でソースの解析をしたっていい。
そもそも複数行であっても問題ない。
もちろん全部やったって構わない。
#endif
のような行を含まない任意のシェルスクリプトを書こう。
ただし、最後に exit
を置くのを忘れないこと 。
この exit
によってシェルスクリプトの実行が終了し、以降の全ての行がシェルから無視される。
ちなみに、このように exit
等の後ろに任意のデータ(時にはバイナリさえ有り得る)を付加する手法は、シェルスクリプト単体でバイナリファイルをインストールするようなインストーラ等で使われたりする。
#endif
C++のコメント終了。
この行では既にシェルスクリプトとしての実行も終了しているから、
この行以降は純粋にC++として見られる。
任意のC++コードを置こう。
そもそも
quickrun等を使うべきって?
確かにそうだろう。私もそう思った。
だが、ファイル毎にコンパイルオプションを設定する方法を探すのが面倒だったのだ。
考えた方が早かったし、結果的に柔軟性もより高い方法になったはずだ。たぶん。
任意のコマンドを実行できるし、エディタに依存しない。
最高だと思わないか。
本当にどうでもいい話
- 上で「C/C++」でなく「C++」と言っている箇所があるが、深い理由はない。思い付いたときC++を書こうとしていたとか、
--std=c++14
オプションを打つのが面倒だと思っていたとか、そんな理由だ。 - 私個人のブログに全く同じような記事がありますが、そっちのサイト丸ごと作り替えるかもしれないのでこっちにコピーしました。元記事も私が書いたやつなのでパクりとか言わないでください。(たぶんQiitaの利用規約でも問題なさげなので)