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;
}
This leads me to the following questions :
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?
From the
boost::fusion
documentation:Which means that if you want a implicit integration of these
operator<<
, you will need to inject theboost::fusion
namespace in your current namespace (::
here), or use them explicitly.To sum it all up, adding:
Should work in your case. Or for an explicit use, you will have to write:
--- EDIT ---
After reading
boost::fusion
's code a bit, it seem that you are confused because of the Koenig's lookup ofboost::fusion::operators::operator<<
which is selected in case your argument is a realboost::fusion::sequence
.This is why you don't need to inject the
boost::fusion
namespace, nor explicitly callboost::fusion::operator<<
for types defined in theboost::fusion
namespace.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.
In this particular case, including
boost/fusion/sequence/io/out.hpp
will defineboost::fusion::operator::operator<<
which will then be injected in theboost::fusion
namespace.This means that calls using
operator<<
with parameters whose types are in theboost::fusion
namespace will find the proper overload.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).You can check that by defining your type in the
boost::fusion
namespace.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: