Metatemplateprogramming is really cool
This commit is contained in:
@@ -14,11 +14,12 @@
|
||||
|
||||
class A: public xml::Serialize {
|
||||
public:
|
||||
std::list<std::string> list;
|
||||
xml::List<std::string> list;
|
||||
protected:
|
||||
void initXmlMembers() {
|
||||
LOG("A::initXmlMembers");
|
||||
className("A");
|
||||
persist(list, "list", "item");
|
||||
persist(list, "list");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,8 +36,8 @@ int main(int, char**) {
|
||||
A a;
|
||||
std::cout<<"Schema:\n"<<a.schema()<<std::endl;
|
||||
a.loadXml(ss);
|
||||
if (a.list.front()=="Hello") a.list.front()="Good Bye";
|
||||
if (a.list.back()=="you") a.list.back()="we";
|
||||
// if (a.list.front()=="Hello") a.list.front()="Good Bye";
|
||||
// if (a.list.back()=="you") a.list.back()="we";
|
||||
a.saveXml(std::cout)<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -829,25 +829,8 @@ namespace xml {
|
||||
virtual ~Serialize();
|
||||
Serialize& operator=(const Serialize& other) throw();
|
||||
Serialize& className(const std::string& name) throw();
|
||||
Serialize& persist(Serialize& member,
|
||||
virtual Serialize& persist(Serialize& member,
|
||||
const std::string& name) throw();
|
||||
template<typename TYPE, class ALLOC>
|
||||
Serialize& persist(std::list<TYPE, ALLOC>& member,
|
||||
const std::string& name) throw() {
|
||||
return persist(member, name, name);
|
||||
}
|
||||
template<typename TYPE, class ALLOC>
|
||||
Serialize& persist(std::list<TYPE, ALLOC>& member,
|
||||
const std::string& list,
|
||||
const std::string& item) throw() {
|
||||
_xmlNames[list] = &member;
|
||||
Serialize ser(list);
|
||||
TYPE dummy;
|
||||
ser.persist(dummy, item);
|
||||
*_xmlFactory<<(xml::Node(list).limits(1,1)
|
||||
<<(*ser._xmlFactory)[0].limits(0, 0));
|
||||
return *this;
|
||||
}
|
||||
Serialize& persist(bool& member,
|
||||
const std::string& name) throw();
|
||||
Serialize& persist(char& member,
|
||||
@@ -885,6 +868,7 @@ namespace xml {
|
||||
protected:
|
||||
virtual void initXmlMembers();
|
||||
private:
|
||||
public: //! @todo
|
||||
void clear() throw();
|
||||
void copy(const Serialize& o) throw();
|
||||
template<typename TYPE>
|
||||
@@ -896,8 +880,8 @@ namespace xml {
|
||||
_xmlFactory = schema;
|
||||
return *this;
|
||||
}
|
||||
void fromNode(boost::any member, const xml::Node& node);
|
||||
void toNode(const boost::any member, xml::Node& node) const;
|
||||
virtual void fromNode(boost::any member, const xml::Node& node);
|
||||
virtual void toNode(const boost::any member, xml::Node& node) const;
|
||||
/*
|
||||
template<typename TYPE, class ALLOC>
|
||||
void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) {
|
||||
@@ -911,6 +895,35 @@ namespace xml {
|
||||
static std::set<ToNodeFunc> _toNode;
|
||||
};
|
||||
|
||||
template<class TYPE, class ALLOC=std::allocator<TYPE> > class List:
|
||||
public std::list<TYPE, ALLOC>, public Serialize {
|
||||
public:
|
||||
List() {}
|
||||
List(const List& o): std::list<TYPE, ALLOC>(o), Serialize(o) {}
|
||||
List(const std::string& className) throw(): Serialize(className) {}
|
||||
virtual ~List() {}
|
||||
protected:
|
||||
/*virtual void initXmlMembers() {
|
||||
LOG("initXmlMembers std::list");
|
||||
//_xmlNames[list] = this;
|
||||
TYPE dummy;
|
||||
std::string itemName("item");
|
||||
if (typeid(TYPE*)==typeid(Serialize*)) {
|
||||
Serialize* ser((Serialize*)&dummy);
|
||||
if (!ser->_xmlFactory) ser->initXmlMembers();
|
||||
itemName = **ser->_xmlFactory;
|
||||
}
|
||||
persist(dummy, itemName);
|
||||
_xmlFactory->limits(0, 0);
|
||||
}
|
||||
virtual void fromNode(boost::any member, const xml::Node& node) {
|
||||
LOG("fromNode std::list");
|
||||
}
|
||||
virtual void toNode(const boost::any member, xml::Node& node) const {
|
||||
LOG("toNode std::list");
|
||||
}*/
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
}
|
||||
|
121
src/xml.cxx
121
src/xml.cxx
@@ -1135,26 +1135,22 @@ namespace xml {
|
||||
}
|
||||
template<typename TYPE> bool assignFromNode(boost::any member,
|
||||
const xml::Node& node) {
|
||||
if (member.type()==typeid(TYPE*)) {
|
||||
if (member.type()!=typeid(TYPE*)) return false;
|
||||
*boost::any_cast<TYPE*>(member) =
|
||||
(TYPE)dynamic_cast<const xml::String&>(node);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<typename TYPE> bool assignToNode(const boost::any member,
|
||||
xml::Node& node) {
|
||||
if (member.type()==typeid(TYPE*)) {
|
||||
if (member.type()!=typeid(TYPE*)) return false;
|
||||
std::stringstream ss;
|
||||
ss<<*boost::any_cast<TYPE*>(member);
|
||||
node.text(ss.str());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<> bool assignFromNode<bool>(boost::any member,
|
||||
const xml::Node& node) {
|
||||
if (member.type()==typeid(bool*)) {
|
||||
if (member.type()!=typeid(bool*)) return false;
|
||||
std::string s(*dynamic_cast<const xml::String&>(node));
|
||||
std::string::size_type
|
||||
start(s.find_first_not_of(" \t\n\r")),
|
||||
@@ -1168,97 +1164,46 @@ namespace xml {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<> bool assignToNode<bool>(const boost::any member,
|
||||
xml::Node& node) {
|
||||
if (member.type()==typeid(bool*)) {
|
||||
if (member.type()!=typeid(bool*)) return false;
|
||||
node.text(*boost::any_cast<bool*>(member)?"true":"false");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<> bool assignFromNode<Serialize>(boost::any member,
|
||||
const xml::Node& node) {
|
||||
if (member.type()==typeid(Serialize*)) {
|
||||
if (member.type()!=typeid(Serialize*)) return false;
|
||||
//! @todo improve this (inefficient)
|
||||
std::stringstream ss; // simple but inefficient: rewrite and reread
|
||||
ss<<node;
|
||||
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<> bool assignToNode<Serialize>(const boost::any member,
|
||||
xml::Node& node) {
|
||||
if (member.type()==typeid(Serialize*)) {
|
||||
if (member.type()!=typeid(Serialize*)) return false;
|
||||
std::stringstream ss;
|
||||
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
|
||||
xml::Factory factory(node);
|
||||
node = *factory.read(ss);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<typename TYPE, class ALLOC>
|
||||
bool containerFromNode(boost::any member,
|
||||
const xml::Node& node) {
|
||||
LOG("ASSIGN List");
|
||||
}
|
||||
// template<typename TYPE, template<class TYPE> class CONTAINER>
|
||||
// bool containerFromNode(boost::any member,
|
||||
// const xml::Node& node) {
|
||||
// if (member.type()!=typeid(TYPE*)) return false;
|
||||
// LOG("ASSIGN List");
|
||||
// return false;
|
||||
// }
|
||||
// template<typename TYPE, class ALLOC>
|
||||
// bool assignToNode(const boost::any member, xml::Node& node) {
|
||||
// }
|
||||
|
||||
void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) {
|
||||
if (!_fromNode.size()) { // initial initialization
|
||||
_fromNode.insert(&assignFromNode<Serialize>);
|
||||
_fromNode.insert(&assignFromNode<std::string>);
|
||||
_fromNode.insert(&assignFromNode<float>);
|
||||
_fromNode.insert(&assignFromNode<double>);
|
||||
_fromNode.insert(&assignFromNode<bool>);
|
||||
_fromNode.insert(&assignFromNode<char>);
|
||||
_fromNode.insert(&assignFromNode<signed char>);
|
||||
_fromNode.insert(&assignFromNode<unsigned char>);
|
||||
_fromNode.insert(&assignFromNode<short>);
|
||||
_fromNode.insert(&assignFromNode<signed short>);
|
||||
_fromNode.insert(&assignFromNode<unsigned short>);
|
||||
_fromNode.insert(&assignFromNode<int>);
|
||||
_fromNode.insert(&assignFromNode<signed int>);
|
||||
_fromNode.insert(&assignFromNode<unsigned int>);
|
||||
_fromNode.insert(&assignFromNode<long>);
|
||||
_fromNode.insert(&assignFromNode<signed long>);
|
||||
_fromNode.insert(&assignFromNode<unsigned long>);
|
||||
}
|
||||
_fromNode.insert(fromNodeFunc);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
|
||||
//----------------------------------------------------------------------------
|
||||
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
|
||||
template<typename TYPE> class RegisterAssignToNode {
|
||||
RegisterAssignToNode() {
|
||||
registerToNode(&assignToNode<TYPE>);
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
|
||||
if (!_toNode.size()) { // initial initialization
|
||||
_toNode.insert(&assignToNode<Serialize>);
|
||||
_toNode.insert(&assignToNode<std::string>);
|
||||
_toNode.insert(&assignToNode<float>);
|
||||
_toNode.insert(&assignToNode<double>);
|
||||
_toNode.insert(&assignToNode<bool>);
|
||||
_toNode.insert(&assignToNode<char>);
|
||||
_toNode.insert(&assignToNode<signed char>);
|
||||
_toNode.insert(&assignToNode<unsigned char>);
|
||||
_toNode.insert(&assignToNode<short>);
|
||||
_toNode.insert(&assignToNode<signed short>);
|
||||
_toNode.insert(&assignToNode<unsigned short>);
|
||||
_toNode.insert(&assignToNode<int>);
|
||||
_toNode.insert(&assignToNode<signed int>);
|
||||
_toNode.insert(&assignToNode<unsigned int>);
|
||||
_toNode.insert(&assignToNode<long>);
|
||||
_toNode.insert(&assignToNode<signed long>);
|
||||
_toNode.insert(&assignToNode<unsigned long>);
|
||||
}
|
||||
_toNode.insert(toNodeFunc);
|
||||
}
|
||||
void Serialize::initXmlMembers() {}
|
||||
@@ -1287,4 +1232,40 @@ namespace xml {
|
||||
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
|
||||
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
|
||||
|
||||
// Register for all simple Types =============================================
|
||||
template<int NUM> struct SimpleTypes {};
|
||||
template<> struct SimpleTypes<1> {typedef std::string Type;};
|
||||
template<> struct SimpleTypes<2> {typedef Serialize Type;};
|
||||
template<> struct SimpleTypes<3> {typedef bool Type;};
|
||||
template<> struct SimpleTypes<4> {typedef unsigned char Type;};
|
||||
template<> struct SimpleTypes<5> {typedef signed char Type;};
|
||||
template<> struct SimpleTypes<6> {typedef char Type;};
|
||||
template<> struct SimpleTypes<7> {typedef unsigned short Type;};
|
||||
template<> struct SimpleTypes<8> {typedef signed short Type;};
|
||||
template<> struct SimpleTypes<9> {typedef short Type;};
|
||||
template<> struct SimpleTypes<10> {typedef unsigned int Type;};
|
||||
template<> struct SimpleTypes<11> {typedef signed int Type;};
|
||||
template<> struct SimpleTypes<12> {typedef int Type;};
|
||||
template<> struct SimpleTypes<13> {typedef unsigned long Type;};
|
||||
template<> struct SimpleTypes<14> {typedef signed long Type;};
|
||||
template<> struct SimpleTypes<15> {typedef long Type;};
|
||||
template<> struct SimpleTypes<16> {typedef float Type;};
|
||||
template<> struct SimpleTypes<17> {typedef double Type;};
|
||||
const int START_NUM(17);
|
||||
// Init To and From Node ---------------------------------------------------
|
||||
namespace {
|
||||
template<int NUM=START_NUM> struct RegisterTemplateForStdTypes {
|
||||
RegisterTemplateForStdTypes<NUM-1> next; // recurse to next until 0
|
||||
RegisterTemplateForStdTypes() {
|
||||
Serialize::registerToNode
|
||||
(&assignToNode<typename SimpleTypes<NUM>::Type>);
|
||||
Serialize::registerFromNode
|
||||
(&assignFromNode<typename SimpleTypes<NUM>::Type>);
|
||||
}
|
||||
};
|
||||
template<> struct RegisterTemplateForStdTypes<0> {}; // stop recursion
|
||||
static RegisterTemplateForStdTypes<> init; // execute initialisation
|
||||
}
|
||||
// ===========================================================================
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user