问题
Assume I have
struct cat
{
int tail;
int head;
};
struct bird
{
int wing;
int bursa;
};
If I do this...
struct wat : public cat, public bird
{
};
BOOST_FUSION_ADAPT_STRUCT(cat,tail,head)
BOOST_FUSION_ADAPT_STRUCT(bird, wing, bursa)
BOOST_FUSION_ADAPT_STRUCT(wat, wat::cat, wat::bird)
... I cannot get a build, but if I explicit refer to the inherited objects like what's below, it's perfectly valid.
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace qi = boost::spirit::qi;
struct wat
{
public:
cat z;
bird q;
};
BOOST_FUSION_ADAPT_STRUCT(cat,tail,head)
BOOST_FUSION_ADAPT_STRUCT(bird, wing, bursa)
BOOST_FUSION_ADAPT_STRUCT(wat, z, q)
Is there some way to make the first version work, such that I can adapt a struct of inhereted public members? I definitely do NOT want to do BOOST_FUSION_ADAPT_STRUCT(wat,tail,head,wing,bursa)
but this seems to be the only way to get there with inherited members I can find.
回答1:
Similar question here: c++/boost fusion handle parent class
Short question: no that's not a feature.
You can use aggregation instead of inheritance,
struct wat {
cat _cat;
bird _bird;
};
BOOST_FUSION_ADAPT_STRUCT(wat, _cat, _bird)
but you won't magically get a flattened sequence.
What you might want to do in your code that treats fusion sequences, is code the support for known base classes and handle them in addition to the adapted sequence members.
Demo With Aggregation
Live On Coliru
#include <boost/fusion/include/adapted.hpp>
struct cat {
int tail;
int head;
};
struct bird {
int wing;
int cloaca;
};
struct wat {
cat _cat;
bird _bird;
};
BOOST_FUSION_ADAPT_STRUCT(cat, tail, head)
BOOST_FUSION_ADAPT_STRUCT(bird, wing, cloaca)
BOOST_FUSION_ADAPT_STRUCT(wat, _cat, _bird)
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
template <typename T, int N = 0> void print(T const& obj) {
namespace fus = boost::fusion;
if constexpr (fus::traits::is_sequence<T>::value) {
if (N==0)
std::cout << "{";
if constexpr (N < fus::size(obj).value) {
auto name = boost::fusion::extension::struct_member_name<T, N>::call();
std::cout << ' ' << name << '=';
print(fus::at_c<N>(obj));
std::cout << ';';
print<T, N+1>(obj);
} else {
std::cout << " }";
}
} else {
std::cout << obj;
}
}
int main() {
print(wat { {1,2}, {3,4} });
}
Prints
{ _cat={ tail=1; head=2; }; _bird={ wing=3; cloaca=4; }; }
Demo With Hardcoded Lists Of Bases
Live On Coliru
#include <boost/fusion/include/adapted.hpp>
struct cat {
int tail;
int head;
};
struct bird {
int wing;
int cloaca;
};
struct wat : cat, bird {
int something;
int extra;
wat(int tail, int head, int wing, int cloaca, int something, int extra)
: cat{tail, head}, bird{wing, cloaca}, something(something), extra(extra)
{ }
};
BOOST_FUSION_ADAPT_STRUCT(cat, tail, head)
BOOST_FUSION_ADAPT_STRUCT(bird, wing, cloaca)
BOOST_FUSION_ADAPT_STRUCT(wat, something, extra)
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
template <typename... KnownBases>
struct Demo {
template <typename T, int N = 0> static void print(T const& obj, bool outer_sequence_braces = true) {
namespace fus = boost::fusion;
if constexpr (fus::traits::is_sequence<T>::value) {
if (N==0)
{
if (outer_sequence_braces) std::cout << "{";
print_bases<KnownBases...>(obj);
}
if constexpr (N < fus::size(obj).value) {
auto name = boost::fusion::extension::struct_member_name<T, N>::call();
std::cout << ' ' << name << '=';
print(fus::at_c<N>(obj), true/*inner sequences get braces*/);
std::cout << ';';
print<T, N+1>(obj, outer_sequence_braces);
} else {
if (outer_sequence_braces) std::cout << " }";
}
} else {
std::cout << obj;
}
}
template <typename Base, typename T> static bool print_base(T const& obj) {
if constexpr (not std::is_same<Base, T>() && std::is_base_of<Base, T>())
print(static_cast<Base const&>(obj), false);
return true;
}
template <typename... Bases, typename T> static void print_bases(T const& obj) {
bool discard[] = { print_base<Bases>(obj)... };
(void) discard;
}
};
int main() {
Demo<cat, bird>::print(wat { 1, 2, 3, 4, 5, 6 });
}
Prints
{ tail=1; head=2; wing=3; cloaca=4; something=5; extra=6; }
来源:https://stackoverflow.com/questions/47820378/can-i-use-boost-fusion-adapt-struct-with-inherited-stuff