|
1: 2018-02-12 (月) 01:13:17 takatsuka |
| + | C++ だと文字列をフォーマットするコードって結構大変です。 |
| + | C++11(14) になって色々な選択肢は増えたんですが、いまいち決定打に欠けると言いますか・・。 |
| | | |
| + | というわけで boost です。boost::format を使った文字列フォーマットです。 |
| + | % で繋げることなく、可変引数テンプレートを使って printf 風に使えるようにしてみました。 |
| + | boost::format の機能のおかげで、型安全で例外が発生することもないようにしています。 |
| + | |
| + | &font(80%){例えばアプリで処理失敗が発生したときに、アプリログを残す際に sprintf などを使ってフォーマットしてるような場合、その書式をミスっていたりすると、アプリが落ちたりしちゃいます。&br;レアケース(処理失敗)を考慮したコードを書いたつもりが、再現率が低く修正しにくい致命的なバグを生んでしまったりするので、できれば、こういう箇所は特に安全に書いておきたいなと思う次第。&br;というわけで、}; |
| + | |
| + | printf 系の関数は(windows の CString::Format とかも)使わないほうが安全です。 |
| + | がしかし printf 系の使いやすさは捨て難いです。慣れちゃってもいるし。 |
| + | |
| + | そんなわけで printf 風の書き方も出来てしまう boost::format はすごく便利です。 |
| + | 開発者の方に感謝しつつ使わせていただこうと思います。 |
| + | |
| + | #prettify{{ |
| + | namespace String |
| + | { |
| + | |
| + | template <class CharT> std::basic_string<CharT> Format(const boost::basic_format<CharT> &format) |
| + | { |
| + | return format.str(); |
| + | } |
| + | |
| + | template <class CharT,class Head,class... Tail> std::basic_string<CharT> Format(boost::basic_format<CharT> &format,Head&& head, Tail&&... tail) |
| + | { |
| + | return Format<CharT>( format % head, tail... ); |
| + | } |
| + | |
| + | template <class CharT,class... Args> std::basic_string<CharT> Format(const CharT *lpszFormat,Args&&... args) |
| + | { |
| + | boost::basic_format<CharT> format(lpszFormat); |
| + | format.exceptions( boost::io::no_error_bits ); // 例外を発生させない |
| + | return Format<CharT>(format,args...); |
| + | } |
| + | |
| + | } |
| + | |
| + | // 使い方例 |
| + | int main() |
| + | { |
| + | |
| + | std::string s0 = String::Format( "%s %dSX SR%dDE%s", "日産", 180, 20, "T" ); // s0 = "日産 180SX SR20DET" |
| + | |
| + | std::wstring ws0 = String::Format( L"BNR%d RB%dDE%s", 32, 26, L"TT" ); // ws0 = L"BNR32 RB26DETT" std::wstring も可です |
| + | |
| + | std::string s1 = String::Format( "%s %dSX SR%dDE%s", 180, 20, "T", L"日産" ); // s1 = "180 20SX SRTDE01909714" 例外発生しません |
| + | |
| + | const std::string s2a = u8"トヨタ"; |
| + | const std::string s2b = "1JZ-GTE"; |
| + | std::string s2c = String::Format( "%s jzx90 %s", s2a, s2b ); // s2c = "トヨタ jzx90 1JZ-GTE" std::string をそのまま書けます。 c_str() は不要です。便利! |
| + | } |
| + | }} |