読者です 読者をやめる 読者になる 読者になる

GCC 4.5でOvenが動かない

C++

GCC 4.5 + Boost 1.42.0 + P-State 1.04.3で以下のコードがコンパイル通りません。

#include <iostream>
#include <vector>
#include <pstade/oven/filtered.hpp>

namespace oven = pstade::oven;

template <class R, class F>
void for_each(const R& r, F f)
{
    std::for_each(boost::begin(r), boost::end(r), f);
}

struct is_even {
    typedef bool result_type;
    bool operator()(int x) const { return x % 2 == 0; }
};

struct disp {
    typedef void result_type;
    void operator()(int x) const { std::cout << x << std::endl; }
};

int main()
{
    const std::vector<int> v = {1,2,3,4,5};
    for_each(v | oven::filtered(is_even()), disp()); // エラー!
}

これがエラーになる原因のひとつは、つい先日Boostの開発者MLで上がってたBoost.MPLのADLに関する問題。


【1.43】【beta】 Fix for MPL under gcc 4.5

【MPL】 gcc-4.5 compilation problems related to arity_helper


これは後者のリンク先にあるパッチで改善されます。
この修正がBoost 1.43.0に入るかはどうかは、時期的に難しいかもしれません。


このパッチでだいぶコンパイルエラーがとれるのですが、
いまだに以下のエラーが残っていて原因がいまだわからない状態です。

In file included from /boost/boost_1_42_0/boost/range/iterator.hpp:19:0,
                 from /boost/boost_1_42_0/boost/range/begin.hpp:24,
                 from /pstade/pstade_1_04_3/pstade/oven/filtered.hpp:20,
                 from main.cpp:3:
/boost/range/mutable_iterator.hpp: In instantiation of 'boost::range_mutable_iterator<mpl_::arg<-0x000000001> >':
/boost/boost_1_42_0/boost/mpl/eval_if.hpp:60:31:   instantiated from 'boost::mpl::eval_if_c<false, boost::range_const_iterator<mpl_::arg<-0x000000001> >, boost::range_mutable_iterator<mpl_::arg<-0x000000001> > >'
/boost/boost_1_42_0/boost/range/iterator.hpp:63:63:   instantiated from 'boost::range_iterator<mpl_::arg<-0x000000001> >'
/pstade/pstade_1_04_3/pstade/oven/././range_iterator.hpp:35:1: instantiated from 'pstade::oven::range_iterator<mpl_::arg<-0x000000001> >'
/pstade/pstade_1_04_3/pstade/oven/filtered.hpp:44:9:   instantiated from 'pstade::oven::filtered_detail::base<mpl_::arg<-0x000000001>, mpl_::arg<-0x000000001> >'
main.cpp:28:39:   instantiated from here /boost/boost_1_42_0/boost/range/mutable_iterator.hpp:37:52: error: no type named 'iterator' in 'struct mpl_::arg<-0x000000001>'

MPLのプレースホルダーの置き換えがうまくいってなさそうなので、
operator|()ではなく、make_*を使ってみたらそっちはコンパイルが通りました。

#include <iostream>
#include <vector>
#include <pstade/oven/filtered.hpp>

namespace oven = pstade::oven;

template <class R, class F>
void for_each(const R& r, F f)
{
    std::for_each(boost::begin(r), boost::end(r), f);
}

struct is_even {
    typedef bool result_type;
    bool operator()(int x) const { return x % 2 == 0; }
};

struct disp {
    typedef void result_type;
    void operator()(int x) const { std::cout << x << std::endl; }
};

int main()
{
    const std::vector<int> v = {1,2,3,4,5,6};
    for_each(oven::make_filtered(v, is_even()), disp()); // OK
}

さて、あとはどこが悪いのだろう。もう3日くらい調べてます。