[英]Limits of BOOST_FUSION_ADAPT_STRUCT
我嘗試使用BOOST_FUSION_ADAPT_STRUCT
宏並嘗試了一些天真的東西,比如使用Fusion打印任意結構。
從文檔中給出的示例代碼開始,我無法在我的自適應結構上執行融合序列允許的一些操作。
#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不能在這里運行?
使用視圖是打印適應結構的正確方法嗎?
改編后的結構可以用多遠作為融合序列?
來自boost::fusion
文檔:
I / O運算符在命名空間boost :: fusion中被重載
這意味着如果你想要隱式集成這些operator<<
,你需要在你當前的命名空間( ::
here)中注入boost::fusion
命名空間,或者明確地使用它們。
總結一下,添加:
using namespace boost::fusion;
應該適合你的情況。 或者為明確使用,您必須寫:
boost::fusion::operator<<(std::cout, e) << std::endl;
---編輯---
稍微閱讀了boost::fusion
的代碼之后,由於Koenig對boost::fusion::operators::operator<<
的查找 ,你似乎很困惑,因為你的參數是真正的boost::fusion::sequence
。
這就是為什么你不需要注入boost::fusion
的命名空間,也沒有顯式調用boost::fusion::operator<<
在定義類型boost::fusion
的命名空間。
一些解釋:
我不會在這里解釋Koenig的查找的整個概念(也稱為Argument Dependent Lookup - ADL),因為這不是重點,但基本上,它表明如果你使用的是一個類型在命名空間內的變量,那么函數查找擴展到該參數的命名空間。
在這種特殊情況下,包括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
}}
這意味着使用 operator<<
的參數類型在 boost::fusion
命名空間 中的調用 將找到正確的重載。
使用類型不在此命名空間中的參數調用將無法解決operator<<
的正確重載(在您的示例中就是這種情況)。
您可以通過在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
附注:如果要調試這些名稱查找問題,則應使用gdb
。 這樣,您將始終知道選擇了哪個過載。 在這種情況下:
$ 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);
非常感謝Aurelien的詳細解釋。 我也在Google群組上發現了這篇帖子 。 正如您的解釋所導致的那樣,最簡單的方法是將它放在演示命名空間中:
namespace demo{
using boost::fusion::operators::operator<<;
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.