[英]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
的代码之后,由于Koenig对boost::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.