Sprout.Weed でアンダーバー区切りの2進数をパース
某掲示板で見かけたのでやってみました。
アンダーバー区切りの2進数文字リテラルを Sprout.Weed を使ってコンパイル時に整数に変換します。
[ソース]
#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION #include <sprout/weed.hpp> template<typename Parsed> constexpr long long int binary_parsed(Parsed&& parsed){ return parsed.success() ? parsed.attr() : 0; } template<typename String> constexpr long long int parse_binary(String const& str){ namespace w = sprout::weed; return binary_parsed(w::parse(str.begin(), str.end(), w::bin32 >> w::eoi)); } template<typename Parsed> constexpr long long int remove_under_bar_binary_parsed(Parsed&& parsed){ return parsed.success() ? parse_binary(parsed.attr()) : 0; } constexpr long long int remove_under_bar_binary(char const* str, std::size_t len){ namespace w = sprout::weed; return remove_under_bar_binary_parsed(w::parse(str, str+len, *w::lim<32>((w::char_('1')|w::char_('0')) >> *w::omit['_']) // *w::lim<32>((w::char_('1')|w::char_('0')) >> *w::omit[w::char_ - '1' - '0']) )); } constexpr long long int operator "" _bin(char const* str, std::size_t len){ return remove_under_bar_binary(str, len); } int main(){ namespace w = sprout::weed; static_assert("1111_1111"_bin == 0xff, ""); static_assert("0111_1110"_bin == 0x7e, ""); static_assert("1111_1011_0111_1110"_bin == 0xfb7e, ""); static_assert("1011__"_bin == 0xb, ""); return 0; }
まぁやっていることは単にアンダーバーを取り除いているだけなので、特に4文字区切りとかはでないですね。
constexpr な関数内で Sprout.Weed を使おうとすると死んでしまいますね。