1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
//=========================================================================
// AbsReader.hh
//
// Template implementation of a factory pattern for reading objects from
// C++ streams. Derive a reader for your concrete inheritance hierarchy
// from the "DefaultReader" template (as illustrated by the examples
// provided with the package). Wrap your reader using the "StaticReader"
// template when the actual reading is performed to ensure that the reader
// factory is unique.
//
// The classes which can be read must implement the static "read" function
// which creates objects on the heap. The signature of this function is
//
// static ClassName* read(const ClassId& id, std::istream& is);
//
// In this function, the class id argument can be used to implement object
// versioning. The "read" method must always succeed. If it is unable to
// build the object, it must throw an exception which inherits from
// std::exception.
//
// I. Volobouev
// September 2010
//=========================================================================
#ifndef GENERS_ABSREADER_HH_
#define GENERS_ABSREADER_HH_
#include "Alignment/Geners/interface/IOException.hh"
#include <map>
#include <sstream>
#include <string>
#include "Alignment/Geners/interface/ClassId.hh"
namespace gs {
template <class Base>
struct AbsReader {
virtual ~AbsReader() {}
virtual Base *read(const ClassId &id, std::istream &in) const = 0;
};
template <class Base, class Derived>
struct ConcreteReader : public AbsReader<Base> {
~ConcreteReader() override {}
inline Derived *read(const ClassId &id, std::istream &in) const override {
// Assume that Derived::read(id, in) returns a new object
// of type "Derived" allocated on the heap
return Derived::read(id, in);
}
};
template <class Base>
class DefaultReader : public std::map<std::string, AbsReader<Base> *> {
public:
typedef Base value_type;
inline DefaultReader() : std::map<std::string, AbsReader<Base> *>() {}
virtual ~DefaultReader() {
for (typename std::map<std::string, AbsReader<Base> *>::iterator it = this->begin(); it != this->end(); ++it)
delete it->second;
}
inline Base *read(const ClassId &id, std::istream &in) const {
typename std::map<std::string, AbsReader<Base> *>::const_iterator it = this->find(id.name());
if (it == this->end()) {
std::ostringstream os;
os << "In gs::DefaultReader::read: class \"" << id.name() << "\" is not mapped to a concrete reader";
throw gs::IOInvalidArgument(os.str());
}
return it->second->read(id, in);
}
DefaultReader(const DefaultReader &) = delete;
DefaultReader &operator=(const DefaultReader &) = delete;
};
// A trivial implementation of the Meyers singleton for use with reader
// factories. Naturally, this assumes that all factories are independent
// from each other (otherwise we are getting into trouble with undefined
// singleton destruction order). Also, this particular code is not
// thread-safe (but should become thread-safe in C++11 if I understand
// static local initialization guarantees correctly).
//
// Assume that "Reader" is derived from "DefaultReader" and that it
// publishes its base class as "Base".
//
template <class Reader>
class StaticReader {
public:
typedef typename Reader::Base::value_type InheritanceBase;
static const Reader &instance() {
static const Reader obj;
return obj;
}
template <class Derived>
static void registerClass() {
Reader &rd = const_cast<Reader &>(instance());
const ClassId &id(ClassId::makeId<Derived>());
delete rd[id.name()];
rd[id.name()] = new ConcreteReader<InheritanceBase, Derived>();
}
// Disable the constructor
StaticReader() = delete;
};
} // namespace gs
#endif // GENERS_ABSREADER_HH_
|