Boost.Phoenix の statement

前回の続きで、Boost.Phoenix の statement です。

[ソース]

#include <boost/phoenix/statement.hpp>
#include <boost/phoenix/core/argument.hpp>
#include <boost/phoenix/core/reference.hpp>
#include <boost/phoenix/core/value.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <exception>
#include <stdexcept>

int
main(){
    namespace phx = boost::phoenix;
    using phx::arg_names::arg1;

    int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    
    std::cout << "block" << std::endl;
    int sum = 0;
    boost::for_each(array,(
        std::cout << arg1 << ",",
        phx::ref(sum) += arg1
    ));
    std::cout << sum << std::endl;
    
    std::cout << "if" << std::endl;
    sum = 0;
    boost::for_each(array,
        phx::if_(arg1 % 2 == 0)[
            std::cout << arg1 << ",",
            phx::ref(sum) += arg1
        ]
    );
    std::cout << sum << std::endl;
    
    std::cout << "if_else" << std::endl;
    boost::for_each(array,
        phx::if_(arg1 > 5)[
            std::cout << arg1 << " > 5\n"
        ]
        .else_[
            phx::if_( arg1 == 5 )[
                std::cout << arg1 << " == 5\n"
            ]
            .else_[
                std::cout << arg1 << " < 5\n"
            ]
        ]
    );
    
    std::cout << "switch" << std::endl;
    boost::for_each(array,
        phx::switch_(arg1)[
            phx::case_<1>(std::cout << phx::val("one") << "\n" ),
            phx::case_<2>(std::cout << phx::val("two") << "\n" ),
            phx::default_(std::cout << phx::val("other value") << "\n" )
        ]
    );
    
    std::cout << "while" << std::endl;
    boost::for_each(array,(
        phx::while_(arg1--)[
            std::cout << arg1 << ","
        ],
        std::cout << phx::val("\n")
    ));
    // 上記の場合は、array が破壊的に変更されているので注意
    // array を修正
    int i = 0;
    boost::for_each(array,(
        std::cout << arg1 << ",",
        arg1 = phx::ref(i),
        ++phx::ref(i)
    ));
    std::cout << "\n";
    
    std::cout << "do while" << std::endl;
    boost::for_each(array,(
        phx::do_[
            std::cout << arg1 << ","
        ]
        .while_(arg1--),
        std::cout << phx::val("\n")
    ));
    // array を修正
    i = 0;
    boost::for_each(array,(
        arg1 = phx::ref(i),
        ++phx::ref(i)
    ));
    
    std::cout << "for" << std::endl;
    int iii;
    boost::for_each(array,(
        phx::for_(phx::ref(iii) = 0, phx::ref(iii) < arg1 , ++phx::ref(iii))[
            std::cout << arg1 << ","
        ],
        std::cout << phx::val("\n")
    ));
    
    std::cout << "try-catch throw" << std::endl;
    boost::function<void(int)> f2 = phx::try_[
        phx::switch_(arg1)[
            phx::case_<0>(phx::throw_(std::runtime_error("runtime_error"))),
            phx::case_<1>(phx::throw_("error")),
            phx::default_(std::cout << phx::val("ok\n"))
        ]
    ]
    .catch_<std::runtime_error>()[
        std::cout << phx::val("runtime_error\n")
    ]
    .catch_all[
        std::cout << phx::val("exception\n")
    ];
    f2(0);
    f2(1);
    f2(2);
    
    return 0;
}

[出力]

block
0,1,2,3,4,5,6,7,8,9,45
if
0,2,4,6,8,20
if_else
0 < 5
1 < 5
2 < 5
3 < 5
4 < 5
5 == 5
6 > 5
7 > 5
8 > 5
9 > 5
switch
other value
one
two
other value
other value
other value
other value
other value
other value
other value
while

0,
1,0,
2,1,0,
3,2,1,0,
4,3,2,1,0,
5,4,3,2,1,0,
6,5,4,3,2,1,0,
7,6,5,4,3,2,1,0,
8,7,6,5,4,3,2,1,0,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
do while
0,
1,0,
2,1,0,
3,2,1,0,
4,3,2,1,0,
5,4,3,2,1,0,
6,5,4,3,2,1,0,
7,6,5,4,3,2,1,0,
8,7,6,5,4,3,2,1,0,
9,8,7,6,5,4,3,2,1,0,
for

1,
2,2,
3,3,3,
4,4,4,4,
5,5,5,5,5,
6,6,6,6,6,6,
7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,
9,9,9,9,9,9,9,9,9,
try-catch throw
runtime_error
exception
ok

ソース見てもらえれば何をやっているのか、なんとなく分かると思います。
複数の処理を簡単に呼べるのがかなり強力ですね……。
Boost.Phoenix ぱない。

[boost]

  • ver 1.47.0