c++/boost融合处理父类
c++/boost fusion handle parent class
假设我有这样的类层次结构:
enum class Type { DUMMY };
struct Base {
int a;
explicit Base(int a) : a(a) {}
virtual ~Base() {}
virtual Type type() = 0;
};
struct Foo1 : public Base {
double b;
Foo1(int a, double b) : Base{a}, b(b) {}
Type type() override { return Type::DUMMY; }
};
所有这些都是使用单一继承从Base
派生的,并且未定义任何virtual
方法,重写type()
方法除外。
我希望从Base
中获得每个的元信息,以便序列化和调试输出。正如我所看到的,助推聚变正是我想要的:
#include <iostream>
#include <string>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/zip.hpp>
#include <boost/mpl/range_c.hpp>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
enum class Type { DUMMY };
struct Base {
int a;
explicit Base(int a) : a(a) {}
virtual ~Base() {}
virtual Type type() = 0;
};
struct Foo1 : public Base {
double b;
Foo1(int a, double b) : Base{a}, b(b) {}
Type type() override { return Type::DUMMY; }
};
BOOST_FUSION_ADAPT_STRUCT(Foo1, (double, b))
template <typename Sequence> struct XmlFieldNamePrinter {
XmlFieldNamePrinter(const Sequence &seq) : seq_(seq) {}
const Sequence &seq_;
template <typename Index> void operator()(Index idx) const {
std::string field_name =
fusion::extension::struct_member_name<Sequence, idx>::call();
std::cout << '<' << field_name << '>' << fusion::at<Index>(seq_) << "</"
<< field_name << ">n";
;
}
};
template <typename Sequence> void printXml(Sequence const &v) {
typedef mpl::range_c<unsigned, 0, fusion::result_of::size<Sequence>::value>
Indices;
fusion::for_each(Indices(), XmlFieldNamePrinter<Sequence>(v));
}
int main() {
Foo1 saveMe = {3, 3.4};
printXml(saveMe);
}
但是如何处理Base
数据迷呢?我不想将它们的描述包括在CCD_ 6中,像这样:
BOOST_FUSION_ADAPT_STRUCT(Foo1,
(int, a)
(double, b))
因为我必须对从CCD_ 7继承的每个结构执行此操作,所以我更喜欢类似的语法(当然不是编译的):
BOOST_FUSION_ADAPT_STRUCT(Base, (int, a))
BOOST_FUSION_ADAPT_STRUCT(Foo1,
(Base, __parent__)
(double, b))
如何实现类似的语法?
您需要单独处理融合序列,例如使用SFINAE:
template <typename Index, typename IsSeq = IsSeq<Index> >
typename boost::disable_if<IsSeq, void>::type operator()(Index idx) const {
std::string field_name = fusion::extension::struct_member_name<Sequence, idx>::call();
std::cout << '<' << field_name << '>' << fusion::at<Index>(seq_) << "</" << field_name << ">n";
}
template <typename Index, typename IsSeq = IsSeq<Index> >
typename boost::enable_if<IsSeq, void>::type operator()(Index idx) const {
std::string field_name = fusion::extension::struct_member_name<Sequence, idx>::call();
std::cout << "<" << field_name << ">nt";
typedef typename IsSeq::sequence_type SubSeq;
typedef mpl::range_c<unsigned, 0, fusion::result_of::size<SubSeq>::value> SubIndices;
fusion::for_each(SubIndices(), XmlFieldNamePrinter<SubSeq>(fusion::at<Index>(seq_)));
std::cout << "</" << field_name << ">n";
}
IsSeq<Index>
助手特性的实现如下。现在你可以使用:
BOOST_FUSION_ADAPT_STRUCT(Base, a)
BOOST_FUSION_ADAPT_STRUCT(Foo1, base, b)
并获得
<base>
<a>3</a>
</base>
<b>3.4</b>
现场演示
在Coliru上直播
#include <iostream>
#include <string>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/zip.hpp>
#include <boost/mpl/range_c.hpp>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
enum class Type { DUMMY };
struct Base {
int a;
explicit Base(int a) : a(a) {}
virtual ~Base() {}
virtual Type type() = 0;
Base &base = *this;
};
struct Foo1 : public Base {
double b;
Foo1(int a, double b) : Base{ a }, b(b) {}
Type type() override { return Type::DUMMY; }
};
BOOST_FUSION_ADAPT_STRUCT(Base, a)
BOOST_FUSION_ADAPT_STRUCT(Foo1, base, b)
template <typename Sequence> struct XmlFieldNamePrinter {
XmlFieldNamePrinter(const Sequence &seq) : seq_(seq) {}
const Sequence &seq_;
template <typename Index,
typename T = typename fusion::result_of::at_c<Sequence, Index::value>::type,
typename BareT = typename boost::remove_reference<T>::type
>
struct IsSeq : mpl::bool_<fusion::traits::is_sequence<BareT>::value> {
typedef BareT sequence_type; // if true_
};
template <typename Index, typename IsSeq = IsSeq<Index> >
typename boost::disable_if<IsSeq, void>::type operator()(Index idx) const {
std::string field_name = fusion::extension::struct_member_name<Sequence, idx>::call();
std::cout << '<' << field_name << '>' << fusion::at<Index>(seq_) << "</" << field_name << ">n";
}
template <typename Index, typename IsSeq = IsSeq<Index> >
typename boost::enable_if<IsSeq, void>::type operator()(Index idx) const {
std::string field_name = fusion::extension::struct_member_name<Sequence, idx>::call();
std::cout << "<" << field_name << ">nt";
typedef typename IsSeq::sequence_type SubSeq;
typedef mpl::range_c<unsigned, 0, fusion::result_of::size<SubSeq>::value> SubIndices;
fusion::for_each(SubIndices(), XmlFieldNamePrinter<SubSeq>(fusion::at<Index>(seq_)));
std::cout << "</" << field_name << ">n";
}
};
template <typename Sequence> void printXml(Sequence const &v) {
typedef mpl::range_c<unsigned, 0, fusion::result_of::size<Sequence>::value> Indices;
fusion::for_each(Indices(), XmlFieldNamePrinter<Sequence>(v));
}
int main() {
Foo1 saveMe = { 3, 3.4 };
printXml(saveMe);
}
相关文章:
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将父类对象强制转换为子类的问题
- 在运行时选择父类的实现
- 如何在C++子类中访问父类的私有变量
- 将父类的子类的数据复制到具有相同父类的另一个类
- C++:处理抽象类中的错误时出现问题
- 父类的私有函数会导致对具有相同名称和相似参数的子类中的公共函数的不明确调用
- C++ 将子类的对象添加到父类的向量中
- 两个父类的构造函数的序列
- 为什么我的子类不继承父类的字符串?
- C++调用使用重写函数的父类函数
- 在父类中公开受保护的构造函数
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 如何使父类不重复已经执行的祖父方法
- 如何处理模板类中的复合类型
- c++/boost融合处理父类
- 如何重写父类的事件处理程序
- 为什么孙类的父类不处理祖父类的初始化?