Hatena::ブログ(Diary)

C++でゲームプログラミング

2011-12-01

[]【Vim Advent Calendar 2011】Vim の開発環境【1日目】

これは、Vim Advent Calendar 2011 の1日目の記事です。


[Vim Advent Calendar 2011について]

去年の Advent Calendar には Vim がなかったので、勢いで立てました。

たくさんの方にご参加いただきありがとうございます。

開始前に何とか25人集まりました!

Advent Calendar は25日までですが、それ以降に参加されても全然問題ありません。

Vim について語り足りない方は2週目も参加しましょう!

年越し Vim とかでも問題ありません。

自分が使っている Vim 力を更に高めましょう!


[開発環境晒し]

実は前日まで書くネタが決まっていなくて、いま慌てて書いているのですがVim script で Expression Template みたいな事も考えたのですが流石にマニアック過ぎるので…)簡単に今使っている Vim の開発環境を晒したいと思います。

まだネタが決まっていない方はこんな感じで Vim の環境を晒せばいいんじゃないでしょうか。

(というか、わたし自身が他の方の Vim を見たいだけですが。


[Vim 本体]


[用途]


[カラースキーム]

  • solarized
    • カーソルの色などは自分用にカスタマイズしています。

[フォント]


[画面構成]

  • ウィンドウ
    • 1〜3、ソースファイル+quickfix
  • タブ
    • 1ファイルに対して1タブ

あまり情報が多くなると管理しきれなくなるので、バッファなどはこまめに消すようにしています。


[プラグイン(汎用)]


[プラグインコーディング)]


[コーディング]

幾つかの補完機能が携わった neocomplcache を使用してコーディングを行っています。

f:id:osyo-manga:20111130224345p:image

↓↓↓↓↓↓↓↓↓↓

f:id:osyo-manga:20111130223609p:image


  • [インクルード補完]

f:id:osyo-manga:20111130223605p:image



その他の補完に clang_complete で clang のコード解析機能を利用して、C++ のコード補完を行います。

f:id:osyo-manga:20111130223604p:image


[コードの静的シンタックスチェック]

quickrun.vim を利用して非同期にシンタックスチェックを行っています。

quickrun.vim から quickfix へ出力を行い vim-hier と quickfixstatus でソースコード上に可視化しています。

詳しくはこちらを参照して下さい。


f:id:osyo-manga:20111130223610p:image


[コンパイル実行]

コードのコンパイルは、quickrun.vim で行っています。

quickrun.vim は、vimproc を使用することで、非同期でコンパイル、実行を行うことが出来ます。

f:id:osyo-manga:20111130223607p:image


[コンパイラの切り替え]

quickrun.vim に複数のコンパイラの設定を記述して、unite.vimコンパイラの切り替えを行っています。

詳しくはこちらを参照して下さい。


f:id:osyo-manga:20111130223606p:image


[デバッグ]

pyclewn を使用して Vim 上で GDB を使用したデバッグを行います。

詳しくはこちらを参照して下さい。


f:id:osyo-manga:20111130235839p:image


[来年の抱負]


[次回予告]

明日の Vim Advent Calendar 2011 は、@mattn_jp さんです。

乞うご期待!

To Be Continued...


[その他ブログで取り上げた雑多な記事]

[]【C++11 Advent Calendar 2011】ユーザ定義リテラル【1日目】

これは C++11 Advent Calendar 2011 の1日目の記事です。

1日目の C++11 Advent Calendar 2011 は『ユーザ定義リテラル』ついて書きたいと思います。

出落ちなのは気のせいです。

もし間違っている記述があれば、ご指摘頂けると助かります。


[C++11 Advent Calendar 2011について]

たくさんの方にご参加いただきありがとうございます。

なんとか12月1日までに25人埋めることが出来ました。

Advent Calendar は25日までですが、それ以降に参加されても全然問題ありません。

2週目をやりたい!って方も、この記事のコメントか @manga_osyo までリプくだされば、スケジュール表に追記します。

まだまだ参加される方をお待ちしております!


[C++11 に対応しているコンパイラ]

まだ、C++11 に完全に対応しているコンパイラは存在しません。

コンパイラによって対応している機能が違っているので、手元のコンパイラと照らしあわせて確認して下さい。


今回ネタにする『ユーザ定義リテラル』は、gcc 4.7 でのみ対応しています。

Windows であれば、こちらからバイナリをダウンロードしてきて使用することが出来ます。


[テストコンパイラ]

今回使用したコンパイラです。

  • gcc (GCC) 4.7.0 20111112 (experimental)

[ユーザ定義リテラル]

C++ では、整数や小数、文字列のリテラルを定義する際に修飾子を付けて型定義する事が出来ます。


int          n1 = 42;      // int 型
unsigned int n2 = 42u;     // unsigned int 型
double       n3 = 3.14;    // double 型
float        n4 = 3.14f;   // float 型

C++11 では、uf などをユーザで定義する事が出来るようになりました。


[書き方]

ユーザ定義リテラルoperator ""キーワードにして定義します。


OutputType operator "" _suffix(unsigned long long);
OutputType v = 1234_suffix;        // operator "" _suffix(1234);

""_suffix の間にはスペースが必要なことに注意して下さい。


[ユーザ定義リテラルの名前]

アンダースコアで始まらないサフィックスは標準で予約されているので、アンダースコアから始める必要があります。

(アンダースコアから始まらなくてもコンパイルは通りますが、将来のことを考えて止めておきましょう。


OutputType operator "" _suffix(...);   // Good
OutputType operator "" suffix(...);    // Bad

[文字列リテラル]

文字列リテラルの場合は、文字型文字列の長さを受け取ります。


char const*
operator "" _suffix(char const* str, std::size_t len){
    return str;
}

wchar_t const*
operator "" _suffix(wchar_t const* str, std::size_t len){
    return str;
}

char16_t const*
operator "" _suffix(char16_t const* str, std::size_t len){
    return str;
}

char32_t const*
operator "" _suffix(char32_t const* str, std::size_t len){
    return str;
}

char const*     str1 = "hoge"_suffix;        // char const*
char const*     str2 = u8"hoge"_suffix;      // char const*
wchar_t const*  str3 = L"hoge"_suffix;       // wchar_t const*
char16_t const* str4 = u"hoge"_suffix;       // char16_t const*
char32_t const* str5 = U"hoge"_suffix;       // char32_t const*

char16_t char32_t C++11 で追加された文字型です。

同様に u8""u""U"" といった書き方も C++11 で追加された文字列リテラルです。


[整数と小数]

整数と小数のリテラルの場合は、いくつか書き方があります。


1.それぞれの型で受け取る

unsigned long longlong double で受け取ります。


unsigned long long
operator "" _suffix(unsigned long long n){
    return n;
}

long double
operator "" _suffix(long double d){
    return d;
}

unsigned long long n = 42_suffix;     // operator "" _suffix(42);
long double        d = 3.14_suffix;   // operator "" _suffix(3.14);

2.char const* で受け取る

文字列(char const*)として受け取ります。


char const*
operator "" _suffix(char const* p){
    return p;
}

char const* p = 42_suffix;      // operator "" _suffix("42");
char const* p = 3.14_suffix;    // operator "" _suffix("3.14");

小数の場合は、ピリオドも受け取ることに注意して下さい。

文字列リテラルとは違い、文字列の長さ引数で受け取りません。


3.template<char...> で受け取る

整数と小数は、char 型の可変長テンプレート引数として受け取ることが出来ます。


template<char ...cs>
std::size_t
operator "" _suffix(){
    return sizeof...(cs);
}

std::size_t len1 = 42_suffix;    // operator "" _suffix<'4', '2'>();
std::size_t len2 = 3.14_suffix;  // operator "" _suffix<'3', '.', '1', '4'>();

assert(len1 == 2);
assert(len2 == 4);

このようにリテラルの各文字をテンプレート引数として受け取ります。

char const* と同様に小数の場合は、ピリオドも文字として受け取ることに注意して下さい。

これを利用して、リテラルによって型を変えることも出来たりします。


[符号(+と-)]

符号(+-)は ユーザ定義リテラル引数に渡されずに、リテラルが評価された後で付属されます。


char const*
operator "" _suffix(char const* p){
    return p;
}

// error: wrong type argument to unary minus
-42_suffix;        // - operator "" _suffix("42")

符号を付ける必要があるリテラルは、戻り値型に operator - を定義するか、文字列リテラル("-42"_suffix)などを使用する必要があります。


[リテラル値をテンプレート引数に渡す]

整数や小数のリテラルは、template<char...> で受け取る事が出来るので、それを利用してリテラル値をテンプレート引数に渡すことが出来ます。


namespace detail{

template<std::size_t acc, char ...cs>
struct atoi_impl
    : std::integral_constant<std::size_t, acc>{};

template<std::size_t acc, char c, char ...cs>
struct atoi_impl<acc, c, cs...>
    : atoi_impl<(acc * 10) + (c - '0'), cs...>{};

template<char ...cs>
struct atoi : atoi_impl<0, cs...>{};

}  // namespace detail


// プレースホルダーをユーザ定義リテラルで定義する
typedef std::_Placeholder<1> _1;
template<char ...cs>
std::_Placeholder<detail::atoi<cs...>::value>
operator "" _arg(){
    return {};
}

assert(std::bind(std::plus<int>(), 1_arg, 2_arg)(1, 3) == 4);
assert(std::bind(std::minus<int>(), 1_arg, 3_arg)(1, 3, 2) == -1);

[多倍長整数型を定義]

char const* 型を受け取る多倍長整数型の場合は、ユーザ定義リテラルを使用して定義する事も出来ます。


// char const* を受け取る多倍長整数型
bigint make_bigint(char const*);

bigint
operator "" _bigint(char const* str){
    return make_bigint(str);
}

auto x = 9148108038107407105720570_bigint;
// auto x = make_bigint("9148108038107407105720570");

文字列リテラルで定義するよりも見やすいのではないでしょうか。


[単位のシンタックスシュガーとして扱う]

単位をユーザ定義リテラルで定義します。


namespace SI{

std::chrono::seconds
operator "" _seconds(unsigned long long n){
	return std::chrono::seconds{n};
}

std::chrono::minutes
operator "" _minutes(unsigned long long n){
	return std::chrono::minutes{n};
}

std::chrono::hours
operator "" _hours(unsigned long long n){
	return std::chrono::hours{n};
}

}  // namespace SI

using namespace SI;

auto x = 1_hours + 5_minutes + 30_seconds;

// こっちの記述よりも見やすい気がする
// auto x = hours(1) + minutes(5) + seconds(30);

ユーザ定義リテラルはこういう使われ方が多くなると思います。


[まとめ]

実際のところユーザ定義リテラルは単なるシンタックスシュガーでしかありません。

しかし、整数や小数のリテラル値をテンプレート引数に渡せるのはユーザ定義リテラルの強みです。

今後、どんな普通に使われていくのかが楽しみです。


[次回予告]

明日のC++11 Advent Calendar 2011は、@egtra さんによる、『C++11時代におけるクラスの書き方』です。

とのことなので、乞うご期待!

To Be Continued...


[参考にしたサイト]