首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BOOST_FUSION_ADAPT_STRUCT极限

BOOST_FUSION_ADAPT_STRUCT极限
EN

Stack Overflow用户
提问于 2013-11-27 12:01:26
回答 2查看 5.5K关注 0票数 8

我尝试过使用BOOST_FUSION_ADAPT_STRUCT宏,并尝试了一些幼稚的东西,比如使用融合来打印任意结构。

从这个文档中给出的示例代码开始,我无法在经过调整的结构上执行一些允许进行融合序列的操作。

代码语言:javascript
复制
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence/io/out.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/view.hpp>
#include <iostream>

namespace fuz = boost::fusion;

namespace demo
{
    struct employee
    {
        std::string name;
        int age;
    };
}

// demo::employee is now a Fusion sequence
BOOST_FUSION_ADAPT_STRUCT(
    demo::employee,
    (std::string, name)
    (int, age))

int main()
{
    // tried to initialize an employee like a fusion sequence
    // but it didnt work
    // demo::employee e("bob", 42);

    demo::employee e;
    e.name = "bob";
    e.age = 42;

    // Access struct members with fusion random access functions
    // ok
    std::cout << fuz::at_c<0>(e) << std::endl; 

    // tried to print the struct like any othe fusion sequence
    // didnt work
    // std::cout << e << std::endl;

    // I made it work by using a fusion view
    // is it the right way?
    std::cout << fuz::as_nview<0, 1>(e) << std::endl;
}

这就引出了以下问题:

  • 为什么聚变magik不在这里运作?
  • 使用视图是打印经过调整的结构的正确方法吗?
  • 一个经过调整的结构能在多大程度上被用作融合序列?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-27 17:55:00

来自boost::fusion文档:

I/O操作符在名称空间boost::融合中重载。

这意味着,如果希望对这些operator<<进行隐式集成,则需要将boost::fusion命名空间注入当前命名空间(此处为::),或显式使用它们。

总括而言,补充如下:

代码语言:javascript
复制
using namespace boost::fusion;

应该在你的案子里起作用。或者为了显式地使用,您必须写:

代码语言:javascript
复制
boost::fusion::operator<<(std::cout, e) << std::endl;

--编辑--

在阅读了boost::fusion的代码之后,您似乎感到困惑,因为Koenig的查找 of boost::fusion::operators::operator<<是为了防止您的参数是真正的boost::fusion::sequence而选择的。

这就是为什么您不需要注入boost::fusion命名空间,也不需要为在boost::fusion命名空间中定义的类型显式调用boost::fusion::operator<<

一些解释:

这里我不解释Koenig查找(也称为参数依赖查找 - ADL)的整个概念,因为这不是重点,但基本上,它指出,如果您使用的变量类型在名称空间中,则函数查找扩展到该参数的命名空间。

在这种情况下,包括boost/fusion/sequence/io/out.hpp将定义boost::fusion::operator::operator<<,然后将其注入到boost::fusion命名空间中。

代码语言:javascript
复制
$ cat /usr/local/include/boost/fusion/sequence/io/out.hpp
[...]
namespace boost { namespace fusion
{
    [...]
    namespace operators
    {
        template <typename Sequence>
        inline typename
            boost::enable_if<
               fusion::traits::is_sequence<Sequence>
              , std::ostream&
            >::type // this is just a SFINAE trick to ensure
                    // the function will only be selected for
                    // actual boost::fusion::sequence
        operator<<(std::ostream& os, Sequence const& seq)
        {
            return fusion::out(os, seq); // this will print out the sequence
        }
    }
    using operators::operator<<; // here the operator<< is injected
                                 // in boost::fusion
}}

--这意味着使用带有类型位于 boost::fusion 命名空间中的参数的 operator<< 调用将找到适当的重载。

使用类型不在此命名空间中的参数进行的调用将无法解决operator<<的适当重载(在您的示例中是这样的)。

您可以通过在boost::fusion命名空间中定义类型来检查这一点。

代码语言:javascript
复制
namespace boost { namespace fusion {
struct employee
{
  std::string name;
  int age;
};
}}

BOOST_FUSION_ADAPT_STRUCT(
    boost::fusion::employee,
    (std::string, name)
    (int, age))

[...]
boost::fusion::employee e;
std::cout << e << std::endl; // ADL will work here

附带注意:如果您想调试这类名称查找问题,则应该使用gdb。这样你就会知道选择了哪种过载。在这种情况下:

代码语言:javascript
复制
$ cat fusion.cpp
#include <iostream>
#include <cstdlib>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/io.hpp>

int main(int, char**)
{
  boost::fusion::vector<int, char> foo(42, '?');
  std::cout << foo << std::endl;

  return EXIT_SUCCESS;
}

$ gdb -q ./fusion
Reading symbols for shared libraries ... done
(gdb) b 10
Breakpoint 1 at 0x1000012f7: file fusion.cpp, line 10.
(gdb) r
Starting program: /Users/avallee/Projects/tmp/fusion
Reading symbols for shared libraries ++............................. done

Breakpoint 1, main (unnamed_arg=0x7fff5fbffb60, unnamed_arg=0x7fff5fbffb60) at fusion.cpp:10
10    std::cout << foo << std::endl;
(gdb) s
boost::fusion::operators::operator<< <boost::fusion::vector<int, char, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > (os=@0x7fff762b5f10, seq=@0x7fff5fbffb18) at out.hpp:38
38              return fusion::out(os, seq);
票数 12
EN

Stack Overflow用户

发布于 2013-11-29 10:31:02

非常感谢你的详细解释。我还在groups上找到了这个职位。正如您的解释所导致的,最简单的方法是将其放在演示名称空间中:

代码语言:javascript
复制
namespace demo{
    using boost::fusion::operators::operator<<;
    ...
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20241932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档