エクストリームテキストプロセシング

C++0xをdisってる人をdisる闇のC++軍団たち - Togetterに吹いた。


だがちょっと待ってほしい。C++0xは変態過ぎはしないか。たとえば増田からは「正規表現使いたければそれこそ、Perl使え」と主張するような声もある。このような声に闇のC++軍団たちは謙虚に耳を傾けるべきではないか。


傾けてみた。まず、perlfaq9 - Networking - metacpan.orgをコピペして、

#! /usr/bin/perl

use strict;

my $atom       = qr{[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+};
my $dot_atom   = qr{$atom(?:\.$atom)*};
my $quoted     = qr{"(?:\\[^\r\n]|[^\\"])*"};
my $local      = qr{(?:$dot_atom|$quoted)};
my $domain_lit = qr{\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\]};
my $domain     = qr{(?:$dot_atom|$domain_lit)};
my $addr_spec  = qr{$local\@$domain};

foreach (qw(roll.me.@example.com roll.you@example.com)) {
    print "$_: ", (/^$addr_spec$/o ? "true" : "false"), "\n";
}

実行した。

$ time perl rfc2822_addr_spec.pl 
roll.me.@example.com: false
roll.you@example.com: true

real	0m0.018s
user	0m0.003s
sys	0m0.005s

Boost.Xpressiveで書いてみた。適当にexpressionにしたので正しいかどうかは判らない。

#include <iostream>
#include <string>
#include <vector>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/xpressive/xpressive.hpp>

int main(int argc, char* argv[]) {
    using boost::xpressive::_ln;
    using boost::xpressive::_s;
    using boost::xpressive::_w;
    using boost::xpressive::range;
    using boost::xpressive::set;
    using boost::xpressive::sregex;

    const sregex atom(+(_w|(set='!','#','$','%','&','\'','*','+','/','=','?','^','`','{','}','~','|','-')));
    const sregex dot_atom(atom >> *('.' >> atom));
    const sregex quoted('"' >> *('\\' >> ~_ln | ~(set='\\','"')) >> '"');
    const sregex local(dot_atom | quoted);
    const sregex domain_lit('[' >> *('\\' >> ~_s | set[range('\x21','\x5A') | range('\x5E','\x7E')]) >> ']');
    const sregex domain(dot_atom | domain_lit);
    const sregex addr_spec(local >> '@' >> domain);

    const std::vector<std::string> data = boost::assign::list_of
        ("roll.me.@example.com")
        ("roll.you@example.com")
        ;

    std::cout << std::boolalpha;
    BOOST_FOREACH(const std::string& i, data) {
        std::cout << i << ": " << regex_match(i, addr_spec) << "\n";
    }

    return 0;
}

下記の環境でコンパイルした。ちなみにcodepad.orgではコンパイルできなかった。

$ time g++ -fast rfc2822_addr_spec.cpp -o rfc2822_addr_spec

real	0m9.188s
user	0m8.617s
sys	0m0.538s

実行した。

$ time ./rfc2822_addr_spec
roll.me.@example.com: false
roll.you@example.com: true

real	0m0.019s
user	0m0.001s
sys	0m0.002s

C++使いはもう正規表現をblogに書くな」と言われても良いレベルのコンパイル時間。たった35行のプログラムをコンパイルするのに10秒近くかかるとか、マゾかと。


だが、それがいい