简体   繁体   English

BOOST_FUSION_ADAPT_STRUCT的限制

[英]Limits of BOOST_FUSION_ADAPT_STRUCT

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. 我尝试使用BOOST_FUSION_ADAPT_STRUCT宏并尝试了一些天真的东西,比如使用Fusion打印任意结构。

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

This leads me to the following questions : 这引出了以下问题:

  • Why the Fusion magik does not operate here? 为什么Fusion magik不能在这里运行?

  • Using a view is the correct way to print an adapted struct? 使用视图是打印适应结构的正确方法吗?

  • How far can an adapted struct be used as a Fusion sequence? 改编后的结构可以用多远作为融合序列?

From the boost::fusion documentation: 来自boost::fusion文档:

The I/O operators are overloaded in namespace boost::fusion I / O运算符在命名空间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. 这意味着如果你想要隐式集成这些operator<< ,你需要在你当前的命名空间( :: here)中注入boost::fusion命名空间,或者明确地使用它们。

To sum it all up, adding: 总结一下,添加:

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;

--- EDIT --- ---编辑---

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的代码之后,由于Koenigboost::fusion::operators::operator<< 的查找 ,你似乎很困惑,因为你的参数是真正的boost::fusion::sequence

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. 这就是为什么你不需要注入boost::fusion的命名空间,也没有显式调用boost::fusion::operator<<在定义类型boost::fusion的命名空间。

Some explanations: 一些解释:

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. 我不会在这里解释Koenig的查找的整个概念(也称为Argument Dependent Lookup - ADL),因为这不是重点,但基本上,它表明如果你使用的是一个类型在命名空间内的变量,那么函数查找扩展到该参数的命名空间。

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. 在这种特殊情况下,包括boost/fusion/sequence/io/out.hpp将定义boost::fusion::operator::operator<< ,然后将其注入boost::fusion命名空间。

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

This means that calls using operator<< with parameters whose types are in the boost::fusion namespace will find the proper overload. 这意味着使用 operator<< 的参数类型在 boost::fusion 命名空间 中的调用 将找到正确的重载。

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). 使用类型不在此命名空间中的参数调用将无法解决operator<<的正确重载(在您的示例中就是这种情况)。

You can check that by defining your type in the boost::fusion namespace. 您可以通过在boost::fusion命名空间中定义类型来检查它。

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

Side note: If you want to debug these kind of name lookup issues, you should use gdb . 附注:如果要调试这些名称查找问题,则应使用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);

Thanks a lot Aurelien for your great detailed explanation. 非常感谢Aurelien的详细解释。 I've also found this post on google groups. 我也在Google群组上发现了这篇帖子 As your explanation would lead to, the simplest way to get things working is put this in the demo namespace : 正如您的解释所导致的那样,最简单的方法是将它放在演示命名空间中:

namespace demo{
    using boost::fusion::operators::operator<<;
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 BOOST_FUSION_ADAPT_STRUCT 的替代实现 - Alternative implementation for BOOST_FUSION_ADAPT_STRUCT BOOST_FUSION_ADAPT_STRUCT的boost :: spirit编译问题 - boost::spirit compile issue with BOOST_FUSION_ADAPT_STRUCT 我可以将BOOST_FUSION_ADAPT_STRUCT与继承的东西一起使用吗? - Can I use BOOST_FUSION_ADAPT_STRUCT with inherited stuff? 如何将BOOST_FUSION_ADAPT_STRUCT与子结构一起使用? - How to use BOOST_FUSION_ADAPT_STRUCT with substructures? 当BOOST_FUSION_ADAPT_STRUCT的参数数量为2时,Boost Fusion编译失败 - Boost Fusion compile failure when number of arguments to BOOST_FUSION_ADAPT_STRUCT is 2 使用fusion :: at时C ++:BOOST_FUSION_ADAPT_STRUCT错误 - C++: BOOST_FUSION_ADAPT_STRUCT Error When Using fusion::at 将 boost::qi::rule 与 BOOST_FUSION_ADAPT_STRUCT 一起使用的正确方法是什么? - What is the correct way to use boost::qi::rule with BOOST_FUSION_ADAPT_STRUCT? 我可以将 BOOST_FUSION_ADAPT_STRUCT 与由 std::vector 组成的结构一起使用吗? - Can I use BOOST_FUSION_ADAPT_STRUCT with struct consisting of std::vector? boost :: spirit递归命令式C ++语法:BOOST_FUSION_ADAPT_STRUCT失败 - boost::spirit recursive imperative c++ grammar: BOOST_FUSION_ADAPT_STRUCT fails BOOST_FUSION_ADAPT_STRUCT 使用带有 std::vector 的递归结构<self_type>成员</self_type> - BOOST_FUSION_ADAPT_STRUCT using a recursive struct with a std::vector<self_type> member
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM