【问题标题】:Making FUSION work to display the contents of a structure使 FUSION 工作以显示结构的内容
【发布时间】:2015-12-10 10:03:59
【问题描述】:

以下代码的目的是显示结构的内容。它基于this 的答案。

#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/bind.hpp>

struct Node {
    int a = 4;
    double b = 2.2;
};

BOOST_FUSION_ADAPT_STRUCT(Node, b)

struct print_visitor {
    template <class Index, class C> void operator()(Index, C &c) {
        std::cout << boost::fusion::extension::struct_member_name<
                         C, Index::value>::call() << "="
                  << boost::fusion::at<Index>(c) << std::endl;
    }
};

template <class C> void print_fields(C &c) {
    typedef boost::mpl::range_c<
        int, 0, boost::fusion::result_of::size<C>::type::value> range;
    boost::mpl::for_each<range>(
        boost::bind<void>(print_visitor(), _1, boost::ref(c)));
}

int main() {
    Node n;
    print_fields(n);
}

编译器(gcc 版本 4.8.2)抱怨:

不完整类型的无效使用'struct boost::fusion::result_of::at >' typedef typename T::type type;

这是什么原因,我该如何解决?

这是编译器的完整输出:

-*- mode: compilation; default-directory: "~/SearchLib/AstarWithPolicies/temp/" -*-
Compilation started at Thu Dec 10 11:54:27

make -k 
g++ -Wall -Wextra -Werror -std=c++11 -pedantic -I ~/boost_1_59_0 -I /usr/include/cairomm-1.0/ -I /usr/include/cairo/ -I /usr/include/sigc++-2.0/ -I /usr/lib/x86_64-linux-gnu/sigc++-2.0/include/ -I /usr/include/freetype2/ -g -c temp.cpp
In file included from /home/meir/boost_1_59_0/boost/utility/enable_if.hpp:15:0,
                 from /home/meir/boost_1_59_0/boost/fusion/support/tag_of.hpp:11,
                 from /home/meir/boost_1_59_0/boost/fusion/support/category_of.hpp:12,
                 from /home/meir/boost_1_59_0/boost/fusion/adapted/struct/detail/extension.hpp:14,
                 from /home/meir/boost_1_59_0/boost/fusion/adapted/struct/adapt_struct.hpp:27,
                 from temp.cpp:7:
/home/meir/boost_1_59_0/boost/core/enable_if.hpp: In instantiation of ‘struct boost::lazy_disable_if_c<false, boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> > >’:
/home/meir/boost_1_59_0/boost/core/enable_if.hpp:70:10:   required from ‘struct boost::lazy_disable_if<boost::is_const<Node>, boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> > >’
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5:   required by substitution of ‘template<class N, class Sequence> constexpr typename boost::lazy_disable_if<boost::is_const<Sequence>, boost::fusion::result_of::at<Sequence, N> >::type boost::fusion::at(Sequence&) [with N = mpl_::integral_c<int, 0>; Sequence = Node]’
temp.cpp:26:48:   required from ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34:   required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50:   required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25:   required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97:   required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48:   required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62:   required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19:   required from here
/home/meir/boost_1_59_0/boost/core/enable_if.hpp:63:30: error: invalid use of incomplete type ‘struct boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> >’
     typedef typename T::type type;
                              ^
In file included from /home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic/begin.hpp:14:0,
                 from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/detail/for_each.hpp:11,
                 from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/for_each.hpp:12,
                 from /home/meir/boost_1_59_0/boost/fusion/include/for_each.hpp:11,
                 from temp.cpp:9:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:53:16: error: declaration of ‘struct boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> >’
         struct at;
                ^
temp.cpp: In instantiation of ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’:
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34:   required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50:   required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25:   required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97:   required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48:   required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62:   required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19:   required from here
temp.cpp:26:48: error: no matching function for call to ‘at(Node&)’
                   << boost::fusion::at<Index>(c) << std::endl;
                                                ^
temp.cpp:26:48: note: candidates are:
In file included from /home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic/begin.hpp:14:0,
                 from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/detail/for_each.hpp:11,
                 from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/for_each.hpp:12,
                 from /home/meir/boost_1_59_0/boost/fusion/include/for_each.hpp:11,
                 from temp.cpp:9:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5: note: template<class N, class Sequence> constexpr typename boost::lazy_disable_if<boost::is_const<Sequence>, boost::fusion::result_of::at<Sequence, N> >::type boost::fusion::at(Sequence&)
     at(Sequence& seq);
     ^
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5: note:   substitution of deduced template arguments resulted in errors seen above
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: note: template<class N, class Sequence> constexpr typename boost::fusion::result_of::at<const Sequence, N>::type boost::fusion::at(const Sequence&)
     at(Sequence const& seq);
     ^
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: note:   template argument deduction/substitution failed:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp: In substitution of ‘template<class N, class Sequence> constexpr typename boost::fusion::result_of::at<const Sequence, N>::type boost::fusion::at(const Sequence&) [with N = mpl_::integral_c<int, 0>; Sequence = Node]’:
temp.cpp:26:48:   required from ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34:   required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50:   required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25:   required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97:   required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48:   required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62:   required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19:   required from here
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: error: invalid use of incomplete type ‘struct boost::fusion::result_of::at<const Node, mpl_::integral_c<int, 0> >’
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:53:16: error: declaration of ‘struct boost::fusion::result_of::at<const Node, mpl_::integral_c<int, 0> >’
         struct at;
                ^
make: *** [all] Error 1

Compilation exited abnormally with code 2 at Thu Dec 10 11:54:27

【问题讨论】:

    标签: c++ boost-fusion


    【解决方案1】:

    我在练习使用 MPL 时发现了这篇文章。我来到这里是因为我想打印你成功的struct_member_name。简短的回答是包含<boost/fusion/sequence.hpp>。 fusion::at 需要sequence

    BOOST_FUSION_ADAPT_STRUCT 只是这样做,它不会为目标创建序列。如果您以与访问名称相同的方式访问该值,它将起作用。

    boost::fusion::extension::access::struct_member<C, Index::value>::template apply<C>::call(x)
    

    返回感兴趣的值。但当然,总有更好的方法,这么多代码很丑陋。一旦你将一个序列应用到你的班级,一切都会变得更容易。现在,我没有找到迭代和传递类型的for_eachfusion::for_each 取消引用该值并将其传递给函子。所以我从boost\fusion\sequence\io\out.hpp 中获取了一些代码,这些代码跨越了一个迭代器范围。

    此示例以您的方式、迭代器方式以及直接使用 fusion 的 IO 打印数据。我确定我错过了很多,但这是我实际编写有效的编译时代码的第一天。谢谢你的问题,如果没有它,我可能不会走这么远!

    #include <iostream>
    #include <boost/mpl/range_c.hpp>
    #include <boost/mpl/for_each.hpp>
    #include <boost/fusion/sequence.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    //https://www.boost.org/doc/libs/1_78_0/libs/fusion/doc/html/fusion/support/deduce_sequence.html
    #include <boost/bind/bind.hpp>
    #include <boost/fusion/iterator/distance.hpp>
    struct test {
        int val;
        std::string name;
    };
    BOOST_FUSION_ADAPT_STRUCT(test,val,name)
    
    //the origanal with changes
    struct print_class
    {
        template <class Index, typename T>
        void operator()(Index, T& x) const
        {
            std::cout << "from print_class: " << boost::fusion::extension::struct_member_name<T, Index::value>::call()
                << " = " << boost::fusion::at<Index>(x) << std::endl;
        }
    };
    
    using namespace boost::placeholders;
    template <class C> void print_fields(C& c) {
    
        typedef boost::mpl::range_c<
            int, 0, boost::fusion::result_of::size<C>::type::value> range;
    
        boost::mpl::for_each<range>(
            boost::bind<void>(print_class(), _1, boost::ref(c)));
    }
    
    //I could not find anything like this in the fusion namespace, so...
    //T is a fusion iterator
    namespace boost::fusion {
        template <typename T>
        auto get_name(){return  boost::fusion::extension::struct_member_name<T::seq_type, T::index::value>::call();
        }
    }
    
    //shamelessly stolen from fusion/io....
    namespace {
        using namespace boost;
        namespace bf = fusion;
        struct print_sequence_loop
        {
            template <typename OS, typename First, typename Last>
            static void call(OS&, First&, Last&, mpl::true_)
            {
            }
    
            template <typename OS, typename First, typename Last>
            static void call(OS& os, First& first, Last& last, mpl::false_)
            {
                bf::result_of::equal_to<
                    typename bf::result_of::next<First>::type
                    , Last
                >is_last;
    
                //The code that prints
                os << bf::get_name<First>() << " = ";
                os << *first << std::endl;
                //End the code that prints
    
                call(os, fusion::next(first), last, is_last);
            }
    
            template <typename OS, typename First, typename Last>
            static void call(OS& os, First const& first, Last const& last)
            {
                bf::result_of::equal_to<First, Last> eq;
                call(os, first, last, eq);
            }
        };
        template <typename OS, typename Sequence>
        inline void print_sequence(OS& os, Sequence& seq)
        {
            print_sequence_loop::call(os, fusion::begin(seq), fusion::end(seq));
        }
    }
    
    using boost::fusion::operators::operator<<;
    
    int main() {
        test the_test{ 12,"this is me" };
        print_sequence(std::cout, the_test);
        std::cout << '\n';
        print_fields(the_test);
        std::cout << "\n\n this is using fusions OS\n";
        std::cout << the_test << std::endl;
    }
    

    GCC demo 它适用于 MSVC。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 2023-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多