Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Marekuss 19. 12. 2020, 19:21:34
-
Ahojte kolegovia,
prichadzam si po radu ku skusenejsim :)
Riesim Filter pattern(?) ale zasekol som sa v navrhu:( tak prichadzam s prozbou
majme :
struct Item {
int16_t id;
};
class Rule{
public:
virtual ~Rule(){};
virtual bool operator()(const Item & item) = 0;
};
class RuleLessThan: public Rule {
private:
int16_t id;
public:
RuleLessThan(int16_t iid): id(iid){}
bool operator()(const Item & item){
return item.id < id ? true : false;
}
};
class RuleEqualTo: public Rule {
private:
int16_t id;
public:
RuleEqualTo(int16_t iid): id(iid){};
bool operator()(const Item & item){
return item.id == id ? true : false;
};
};
class Filter {
private:
std::vector<Rule *> v_rule;
public:
Filter(){};
~Filter(){
for(auto & rule : v_rule){
delete rule;
}
};
void add (Rule * rule){
v_rule.push_back(rule);
}
bool apply(const Item & item ){
for(auto & rule : v_rule){
if((*rule)(item) == false){
return false;
}
}
return true;
}
};
int main(void){
Item item_A = {15};
Item item_B = {30};
Item item_C = {40};
Filter filter_A;
Filter filter_B;
filter_A.add(new RuleEqualTo(15));
filter_B.add(new RuleEqualTo(30));
filter_B.add(new RuleLessThan(50));
if(filter_A.apply(item_A) == true){
std::cout << "ok" << std::endl;
}
if(filter_B.apply(item_B) == true){
std::cout << "ok" << std::endl;
}
if(filter_B.apply(item_C) == false){
std::cout << "ok" << std::endl;
}
return 0;
}
majme vsak dalsi mozny vstup do rule a to:
struct Type {
std::string type;
};
napada Vas, ako spravne zakompnovat "Type" do "Filter" a/alebo ako zakomponovat "Type" do "Filter" class?
Primarne ide o to, ze budem mat triedu Filter, ktora bude mat vo "Vector" n-Rules, ale tie by mali byt "Item" tak aj "Type"
Filter bude vediet pouzit .apply() podla typu--
Trocha som sa v navrhu zamotal tak hladam spravnu cestu
Diky
M.
-
Pokud chceš filtr, který se bude dynamicky rozhodovat podle více možných typů vstupu, tak můžeš použít třeba std::variant.
-
Ahoj,
uplne presne jsem nepochopil jak ten dotaz myslis, takze se jeste zeptam:
1) Chtel jsi rict, ze parametr funkce Filter.apply(X) muze byt ruzny? Jakoze to muze byt jak struct Item, tak std::string? Nejlepsi bude kdyz ukazes jak bys to chtel volat.
A pokud ad1) plati, pak:
a) Chces aplikovat vsechny Rule na vstupni hodnotu?
- kazdy Rule se podle typu vstupu muze chovat jinak? Nebo respektive muze mit jiny kod?
- nebo jen chces, aby Rule umel prijmout ruzne typy, ale v podstate prace s nima je vzdy stejna. Ma stejny kod?
b) Chces aby se aplikoval na dany parametr jen ty Rule tridy, ktere ho umi zpracovat? A ostatni ignorovat?
A jeste poznamka: omlouvam se, nechci byt uplne hnidopich, ale dve veci z toho kodu dost krici:
1) Potencialni bug. Ve svem kodu udelas toto:
filter_A.add(new RuleEqualTo(15));
a ve funkci add() pak pridavas nove alokovany Rule do vektoru, ktery pak korektne cistis ve svem destruktoru. Nicmene pokud nekde predtim, nez do vektoru pomoci .push_back() ten pointer vlozis nastane vyjimka (treba v samotnem .push_back()), tak se novy Rule do toho vector<Rule> neprida a timpadem se pri jeho destrukci nebude ani deletovat a timpadem mas leak, protoze ti zustane viset v pameti az do konce behu programu. Dneska uz se operator new fakt neoplati skoro nikdy pouzivat. Kdyzuz pouzivas pointery, tak se koukni na smart pointers. V tomto pripade tedy std::unique_ptr a std::make_unique.
2) kdyz vracis bool hodnotu, tak tam staci podminka :) tedy misto:
return item.id == id ? true : false;
staci napsat napriklad:
return item.id == id;
-
Pokud chceš filtr, který se bude dynamicky rozhodovat podle více možných typů vstupu, tak můžeš použít třeba std::variant.
Super, myslim ze toto by slo, o tej moznosti som ani netusil :)
Ahoj ahoj, totiz , ani ja som sa nevyjadril uplne presne :), nakoniec som musel cvhilku porozmyslat o navrhu a myslim ze to slo :)
Ano, ano, do prikladu som vrazil "new", nastastie bezne pouzivam smart pointre, ich vyhoda je nezrovnatelna :)
Povodny priklad som vyklepal do nasledujuceho tvaru, od zapudzrenia viacerych class (naprikald cez std::variant) do jedneho filtra som upustil. Tak davam na inspiraciu/skomentovanie nasledujuceho kodu:
/* abstract rule template */
template <class T>
class TRule {
public:
virtual ~TRule(){};
virtual bool operator()(const T & t) = 0;
};
template <typename T>
using RulePtr = std::unique_ptr<TRule<T>>;
template <typename T, typename Arg>
std::unique_ptr<T> Rule(Arg&& arg){
return std::make_unique<T>(std::forward<Arg>(arg));
};
template <class T>
class TFilter {
private:
std::vector<RulePtr<T>> v_rule;
public:
TFilter(){};
~TFilter(){};
void add(RulePtr<T> rule){
v_rule.push_back(std::move(rule));
}
bool operator()(const T & t){
for(auto & rule : v_rule){
if((*rule)(t) == false){
return false;
}
}
return true;
}
};
/* Class */
struct Item {
int16_t id;
};
namespace ItemRule {
class LessThan: public TRule<Item> {
private:
int16_t id;
public:
~LessThan(){};
LessThan(int16_t iid): id(iid){};
bool operator()(const Item & item) override{
return item.id < id ? true : false;
}
};
class EqualTo: public TRule<Item> {
private:
int16_t id;
public:
~EqualTo(){};
EqualTo(int16_t iid): id(iid){};
bool operator()(const Item & item) override{
return item.id == id ? true : false;
};
};
};
class ItemFilter : public TFilter<Item>{};
int main(void){
/* test A */
Item item_A = {15};
ItemFilter itemfilter;
itemfilter.add(std::make_unique<ItemRule::EqualTo>(15)); // (1)
itemfilter.add(Rule<ItemRule::LessThan>(20)); // (1)
// (1) equivalent
if(itemfilter(item_A) == true){
std::cout << "ok" << std::endl;
}else{
std::cout << "off" << std::endl;
}
return 0;
}