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 を使おうとすると死んでしまいますね。

[コンパイラ]

  • g++ (GCC) 4.7.0 20111210 (experimental)