BOOST_FUSION_ADAPT_STRUCT的限制 [英] Limits of BOOST_FUSION_ADAPT_STRUCT

查看:66
本文介绍了BOOST_FUSION_ADAPT_STRUCT的限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用BOOST_FUSION_ADAPT_STRUCT宏,并尝试了一些幼稚的操作,例如使用Fusion来打印任意结构.

I have tried to play with the BOOST_FUSION_ADAPT_STRUCT macro and tried some naive things such as use Fusion to print any arbitrary structure.

从此示例开始文档中提供的代码,我无法在适应的结构上执行融合序列允许的某些操作.

Starting from this example code given in the documentation, I was unable to perform on my adapted structure some operations that are allowed with a fusion sequence.

#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;
}

这使我想到以下问题:

  • 为什么Fusion magik无法在此处运行?

  • Why the Fusion magik does not operate here?

使用视图是打印适应的结构的正确方法吗?

Using a view is the correct way to print an adapted struct?

经过修改的结构可以用作融合序列多远?

How far can an adapted struct be used as a Fusion sequence?

推荐答案

来自boost::fusion文档:

I/O操作符在命名空间boost :: fusion中重载

The I/O operators are overloaded in namespace boost::fusion

这意味着,如果要隐式集成这些operator<<,则需要将boost::fusion名称空间注入当前的名称空间(此处为::),或显式使用它们.

Which means that if you want a implicit integration of these operator<<, you will need to inject the boost::fusion namespace in your current namespace (:: here), or use them explicitly.

总而言之,添加:

using namespace boost::fusion;

应该适合您的情况. 或为明确使用,您将必须编写:

Should work in your case. Or for an explicit use, you will have to write:

boost::fusion::operator<<(std::cout, e) << std::endl;

---编辑---

稍微阅读boost::fusion的代码后,您似乎感到困惑,因为 Koenig对boost::fusion::operators::operator<<的查找是在您的参数是真实的boost::fusion::sequence的情况下选择的.

After reading boost::fusion's code a bit, it seem that you are confused because of the Koenig's lookup of boost::fusion::operators::operator<< which is selected in case your argument is a real boost::fusion::sequence.

这就是为什么您无需注入boost::fusion名称空间,也无需显式调用boost::fusion::operator<<来定义boost::fusion名称空间中定义的类型的原因.

This is why you don't need to inject the boost::fusion namespace, nor explicitly call boost::fusion::operator<< for types defined in the boost::fusion namespace.

一些解释:

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

I won't explain the whole concept of Koenig's lookup (also known as Argument Dependent Lookup - ADL) here since that is not the point, but basically, it states that in case you are using a variable whose type is inside a namespace, then the function lookup extends to the namespace of that parameter.

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

In this particular case, including boost/fusion/sequence/io/out.hpp will define boost::fusion::operator::operator<< which will then be injected in the boost::fusion namespace.

$ 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
}}

这意味着使用 operator<< 具有类型在 boost::fusion 命名空间中的参数的调用将找到适当的重载.

使用类型不在此命名空间中的参数进行调用将无法解析operator<<的正确重载(在您的示例中就是这种情况).

Calls using arguments whose type is not located in this namespace will fail to resolve the proper overload of operator<< (this is the case in your example).

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

You can check that by defining your type in the boost::fusion namespace.

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.这样,您将始终知道选择了哪个过载.在这种情况下:

Side note: If you want to debug these kind of name lookup issues, you should use gdb. That way you will always know which overload was chosen. In this case:

$ 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);

这篇关于BOOST_FUSION_ADAPT_STRUCT的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆