Boost Fusion类型转换和as_vector操作

4

我正在努力理解使用Fusion的要点,但在这个简单的例子中遇到了困难:

#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/transform.hpp>

template< typename T >
struct S {
    typedef T type;
};

struct S_f {
    template< typename T >
    struct result {
        typedef typename T::type type;
    };
};

int main () {
    using namespace boost;
    typedef fusion::vector<S<int>> from_type;
    BOOST_MPL_ASSERT((fusion::traits::is_sequence< fusion::vector< int > > ));

    typedef fusion::result_of::transform< from_type, S_f >::type to_type;
    BOOST_MPL_ASSERT((fusion::traits::is_sequence< to_type > ));

    typedef fusion::result_of::as_vector< to_type >::type value_type; // error
}
< p >断言通过,但是value_type的typedef执行失败,错误如下。我在代码和文档之间没有发现任何差异,并且在stackoverflow或boost邮件列表中也没有找到其他解决方法。< /p> < p >据我所知,代码是正确的:应用transform元函数的结果是transform_view,而transform_view是一个序列,这一点可以通过通过的asserts来证明。然而,将as_vector元函数应用于transform_view却失败了。怎么回事?!< /p> < p >任何帮助都将不胜感激。我不想混合mpl。我知道我可以通过MPL绕过问题,但是在SO上有一些关于类型操作的fusion问题回答提倡使用MPL。根据文档,我不需要MPL。< /p>
clang++ -std=c++1z -c t.cpp
In file included from main.cpp:4:
In file included from /usr/local/include/boost/fusion/include/transform.hpp:11:
In file included from /usr/local/include/boost/fusion/algorithm/transformation/transform.hpp:11:
In file included from /usr/local/include/boost/fusion/view/transform_view/transform_view.hpp:15:
In file included from /usr/local/include/boost/fusion/view/transform_view/transform_view_iterator.hpp:18:
/usr/local/include/boost/fusion/view/transform_view/detail/value_of_impl.hpp:37:74: error: no type named 'type' in 'boost::mpl::apply<boost::fusion::detail::apply_transform_result<S_f>, S<int>, mpl_::na, mpl_::na, mpl_::na, mpl_::na>'
                typedef typename mpl::apply<transform_type, value_type>::type type;
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/fusion/iterator/value_of.hpp:52:15: note: in instantiation of template class 'boost::fusion::extension::value_of_impl<boost::fusion::transform_view_iterator_tag>::apply<boost::fusion::transform_view_iterator<boost::fusion::vector_iterator<boost::fusion::vector<S<int>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, 0>, S_f> >' requested here
            : extension::value_of_impl<typename detail::tag_of<Iterator>::type>::
              ^
/usr/local/include/boost/fusion/container/vector/detail/cpp03/preprocessed/as_vector10.hpp:19:49: note: in instantiation of template class 'boost::fusion::result_of::value_of<boost::fusion::transform_view_iterator<boost::fusion::vector_iterator<boost::fusion::vector<S<int>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, 0>, S_f> >' requested here
            typedef typename fusion::result_of::value_of<I0>::type T0;
                                                ^
/usr/local/include/boost/fusion/container/vector/convert.hpp:26:17: note: in instantiation of template class 'boost::fusion::detail::barrier::as_vector<1>::apply<boost::fusion::transform_view_iterator<boost::fusion::vector_iterator<boost::fusion::vector<S<int>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, 0>, S_f> >' requested here
                template apply<typename result_of::begin<Sequence>::type>::type
                ^
main.cpp:26:32: note: in instantiation of template class 'boost::fusion::result_of::as_vector<boost::fusion::transform_view<boost::fusion::vector<S<int>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, S_f, boost::fusion::void_> >' requested here
    typedef fusion::result_of::as_vector< to_type >::type value_type; // error
                               ^
1 error generated.
1个回答

6
模板元编程的问题在于,当您未能满足元函数的前提条件时,会收到许多无意义的错误。transform 的要求是 F 是一个一元 多态函数对象。文档中对此的解释有些含糊不清,但您可以从示例中看出:这是一个可以使用参数调用的对象。也就是说,result_of<F(T)>::type 需要是格式正确的。
您传递给 transform 的内容是:
struct S_f {
    template< typename T >
    struct result {
        typedef typename T::type type;
    };
};

这不是一个多态函数对象,也不是元函数类。这不是Boost.Fusion或Boost.MPL能够理解的内容。特别混淆的是,transform<> 元函数是“惰性”的 - 所以你看起来已经正确处理了那部分。只有在 as_vector<> 中才实际应用了转换,所以看起来失败的关键就在那里。
要将其转换为多态函数对象,只需将嵌套的 result 类模板更改为调用运算符:
struct S_f {
    template< typename T >
    typename T::type operator()(T );
};

不需要定义,因为你实际上并没有调用它。这样修复后,你的代码可以编译。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接