Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
clonable.hpp
Go to the documentation of this file.
1#ifndef FSTCLONABLE_H
2#define FSTCLONABLE_H
3 /*
27=========================================================================
28Copyright and license:
29 * FST4 software (with the exception of any bundled or externally linked
30 third-party components) is Copyright (C) 2000-present Institute of
31 Information Theory and Automation of the Czech Academy of Sciences (UTIA).
32 * FST4 is free software: you can redistribute it and/or modify it under
33 the terms of the GNU Affero General Public License as published by the
34 Free Software Foundation, version 3. The full text of the license is in
35 the file LICENSE in the distribution root and at
36 https://www.gnu.org/licenses/agpl-3.0.html.
37 * FST4 is distributed in the hope that it will be useful, but WITHOUT ANY
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or
39 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
40 License for more details.
41 * Closed-source use without the AGPL's copyleft obligations requires a
42 commercial license from UTIA; in case of interest write to
43 utia@utia.cas.cz. LICENSING.md in the distribution root explains both
44 options, the contributor license agreement that every contribution
45 requires, and the contacts (technical questions and pull requests:
46 somol@utia.cas.cz, with "FST" in the subject line).
47========================================================================== */
48
49#include <cassert>
50#include <iostream>
51#include <memory>
52#include <typeinfo>
53#include <type_traits> // for the contract static_asserts in Clonable_Impl
54#include "error.hpp"
55#include "global.hpp"
56
57/*============== Template parameter type naming conventions ==============
58--------- Numeric types: -------------------------------------------------
59DATATYPE - data sample values - usually real numbers (but may be integers
60 in text processing etc.)
61REALTYPE - must be real numbers - for representing intermediate results of
62 calculations like mean, covariance etc.
63IDXTYPE - index values for enumeration of data samples - (nonnegative) integers,
64 extent depends on numbers of samples in data
65DIMTYPE - index values for enumeration of features (dimensions), or classes (not
66 class sizes) - (nonnegative) integers, usually lower extent than IDXTYPE,
67 but be aware of expressions like _classes*_features*_features !
68 in linearized representations of feature matrices for all classes
69BINTYPE - feature selection marker type - represents ca. <10 different feature
70 states (selected, deselected, sel./desel. temporarily 1st nested loop, 2nd...)
71RETURNTYPE - criterion value: real value, but may be extended in future to support
72 multiple values
73--------- Class types: ---------------------------------------------------
74SUBSET - class of class type Subset
75CLASSIFIER - class implementing interface defined in abstract class Classifier
76EVALUATOR - class implementing interface defined in abstract class Sequential_Step
77DISTANCE - class implementing interface defined in abstract class Distance
78DATAACCESSOR - class implementing interface defined in abstract class Data_Accessor
79INTERVALCONTAINER - class of class type Data_Intervaller
80CONTAINER - STL container of class type Data_Interval
81========================================================================== */
82
83namespace FST {
84
85class Clonable;
86
87std::ostream& operator<<(std::ostream& os, const Clonable& cl);
88
95class Clonable { // abstract class
97 friend std::ostream& operator<<(std::ostream& os, const Clonable& cl);
98public:
99 Clonable(): _clone(false), _sharing(false) {}
100 virtual ~Clonable() {}
101
105 virtual Clonable* clone() const =0;
106
112 virtual Clonable* sharing_clone() const =0;
113
122 virtual Clonable* stateless_clone() const =0;
123
125 bool is_clone() const {return _clone;}
126 bool is_sharing() const {return _sharing;}
127 bool is_sharing_clone() const {return _sharing && _clone;}
128
129 virtual std::ostream& print(std::ostream& os) const {return os;}
130protected:
131 void set_cloned(const bool cloned=true) {_clone=cloned;}
132 void set_sharing(const bool sharing=true) {_sharing=sharing;}
133 void set_sharing_cloned(const bool cloned=true, const bool sharing=true) {_clone=cloned; _sharing=sharing;}
134private:
136 bool _clone;
137 bool _sharing;
138};
139
141inline std::ostream& operator<<(std::ostream& os, const Clonable& cl) {
142 return cl.print(os);
143}
144
154
180template<class Derived, class Base,
181 CloneKind DEEP_KIND = CLONE_DEEP,
182 CloneKind SHARING_KIND = CLONE_INHERIT,
183 CloneKind STATELESS_KIND = CLONE_INHERIT>
184class Clonable_Impl : public Base {
185 static_assert(std::is_base_of<Clonable,Base>::value,
186 "Clonable_Impl: Base must derive from Clonable (family-base contract)");
187public:
188 Base* clone() const override {return make<DEEP_KIND,SLOT_CLONE>();}
189 Base* sharing_clone() const override {return make<SHARING_KIND,SLOT_SHARING>();}
190 Base* stateless_clone() const override {return make<STATELESS_KIND,SLOT_STATELESS>();}
191protected:
192 using Base::Base;
193private:
194 enum Slot {SLOT_CLONE, SLOT_SHARING, SLOT_STATELESS};
195
198 const Derived& self() const {
199 assert(typeid(*this)==typeid(Derived)); // a more-derived class is missing its own Clonable_Impl layer (would slice)
200 return static_cast<const Derived&>(*this);
201 }
202
206 template<CloneKind K, Slot S> Base* make() const {
207 static_assert(std::is_base_of<Clonable_Impl,Derived>::value,
208 "Clonable_Impl: Derived must derive from its own Clonable_Impl (CRTP contract)");
209 if constexpr(K==CLONE_DEEP) {
210 Derived *c=new Derived(self()); c->set_cloned(); return c;
211 } else if constexpr(K==CLONE_WEAK) {
212 Derived *c=new Derived(self(),0); c->set_cloned(); return c;
213 } else if constexpr(K==CLONE_WEAK_SHARING) {
214 Derived *c=new Derived(self(),0); c->set_sharing_cloned(); return c;
215 } else if constexpr(K==CLONE_TO_STATELESS) {
216 return this->stateless_clone();
217 } else if constexpr(K==CLONE_THROW) {
218 throw fst_error("Clonable_Impl: this clone kind is not supported by this class.");
219 } else {
220 // CLONE_INHERIT defers to the Base body, which by family convention throws; the
221 // casts are unreachable at runtime and exist only to satisfy the return type
222 if constexpr(S==SLOT_CLONE) return static_cast<Base*>(Base::clone());
223 else if constexpr(S==SLOT_SHARING) return static_cast<Base*>(Base::sharing_clone());
224 else return static_cast<Base*>(Base::stateless_clone());
225 }
226 }
227};
228
233template<class T>
234std::unique_ptr<T> clone_unique(const T& src) {
235 return std::unique_ptr<T>(static_cast<T*>(src.clone()));
236}
237
238template<class T>
239std::unique_ptr<T> sharing_clone_unique(const T& src) {
240 return std::unique_ptr<T>(static_cast<T*>(src.sharing_clone()));
241}
242
243template<class T>
244std::unique_ptr<T> stateless_clone_unique(const T& src) {
245 return std::unique_ptr<T>(static_cast<T*>(src.stateless_clone()));
246}
247
248} // namespace
249#endif // FSTCLONABLE_H ///:~
CRTP mixin implementing the Clonable protocol for a concrete class.
Definition clonable.hpp:184
Base * clone() const override
dispatches to the DEEP_KIND mechanism (default CLONE_DEEP: Derived's copy-constructor)
Definition clonable.hpp:188
Base * stateless_clone() const override
dispatches to the STATELESS_KIND mechanism (default CLONE_INHERIT: defers to Base,...
Definition clonable.hpp:190
Base * make() const
Constructs the clone per CloneKind K, for the override slot S (see Slot). Only the branch selected by...
Definition clonable.hpp:206
Slot
< inherits Base's constructors, so Derived need not repeat them
Definition clonable.hpp:194
const Derived & self() const
Definition clonable.hpp:198
Base * sharing_clone() const override
dispatches to the SHARING_KIND mechanism (default CLONE_INHERIT: defers to Base, which throws by fami...
Definition clonable.hpp:189
Abstract class, defines interface for classes that may need to get cloned.
Definition clonable.hpp:95
virtual Clonable * clone() const =0
void set_cloned(const bool cloned=true)
marks/unmarks this instance as a clone; call from clone()/stateless_clone() overrides (Clonable_Impl ...
Definition clonable.hpp:131
bool is_clone() const
Definition clonable.hpp:125
virtual Clonable * stateless_clone() const =0
virtual std::ostream & print(std::ostream &os) const
writes a human-readable identification of the object; base default writes nothing
Definition clonable.hpp:129
friend std::ostream & operator<<(std::ostream &os, const Clonable &cl)
Streams a clonable object's print() to os.
Definition clonable.hpp:141
void set_sharing_cloned(const bool cloned=true, const bool sharing=true)
sets both flags at once; call from sharing_clone() overrides (Clonable_Impl does this automatically)
Definition clonable.hpp:133
bool _sharing
set by set_sharing()/set_sharing_cloned(); read by is_sharing()/is_sharing_clone()
Definition clonable.hpp:137
bool _clone
Definition clonable.hpp:136
virtual Clonable * sharing_clone() const =0
bool is_sharing() const
true if this instance is a sharing_clone() result (referencing, not owning, the source's structures)
Definition clonable.hpp:126
bool is_sharing_clone() const
true if this instance is BOTH a clone and sharing – i.e. specifically a sharing_clone() result,...
Definition clonable.hpp:127
void set_sharing(const bool sharing=true)
marks/unmarks this instance as sharing (see is_sharing())
Definition clonable.hpp:132
FST4 specific error passing class.
Definition error.hpp:61
FST4 specific error passing class.
Global definitions.
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
CloneKind
How a Clonable_Impl slot (clone/sharing_clone/stateless_clone) is implemented.
Definition clonable.hpp:146
@ CLONE_TO_STATELESS
forward to stateless_clone() (Classifier_LIBSVM contract)
Definition clonable.hpp:152
@ CLONE_WEAK
new Derived(*this,0) via the weak/referencing copy-constructor, then set_cloned()
Definition clonable.hpp:150
@ CLONE_DEEP
new Derived(*this), then set_cloned()
Definition clonable.hpp:149
@ CLONE_WEAK_SHARING
new Derived(*this,0) via the weak/referencing copy-constructor, then set_sharing_cloned()
Definition clonable.hpp:151
@ CLONE_INHERIT
do not add behavior; defer to the Base class body (typically a family-level throwing default)
Definition clonable.hpp:147
@ CLONE_THROW
throw fst_error (for classes whose Base has no default body to defer to)
Definition clonable.hpp:148
std::ostream & operator<<(std::ostream &os, const Data_Intervaller< CONTAINER, IDXTYPE > &ia)
Streams every contained interval as "si:<startidx>, c:<count>" lines to os.
Definition data_intervaller.hpp:152
std::unique_ptr< T > clone_unique(const T &src)
Definition clonable.hpp:234
std::unique_ptr< T > stateless_clone_unique(const T &src)
stateless_clone() counterpart of clone_unique() – see its comment above.
Definition clonable.hpp:244
std::unique_ptr< T > sharing_clone_unique(const T &src)
sharing_clone() counterpart of clone_unique() – see its comment above.
Definition clonable.hpp:239
Copyright © 2000–present ÚTIA, Institute of Information Theory and Automation of the Czech Academy of Sciences · Contacts · This site sets no cookies and uses no analytics.