I have a class that works as a predicate to select value from list.
class Predicate {
public:
// In this example, I am using QString as value type
// this is not what happens in actual code, where more complex data is being validated
virtual bool evaluate(const QString& val) const = 0;
};
Originally, I used lambda functions but this created lot of repetitive garbage code. So instead, I want to use predicate classes that use inheritance. For example:
class PredicateMaxLength: public RowPredicate {
public:
PredicateMaxLength(const int max) : maxLength(max) {}
virtual bool evaluate(const QString& val) const {return val.length()<maxLength;}
protected:
const int maxLength;
};
To allow inheritance do it's deed, pointers are given rather than values:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(const std::shared_ptr<Predicate> pred);
}
Now we are surely stil going to use lambdas in cases where code would not be repetitive (eg. some special case). For this purpose, PredicateLambda
has been created:
typedef std::function<bool(const QString& val)> StdPredicateLambda;
class PredicateLambda: public Predicate {
public:
PredicateLambda(const StdPredicateLambda& lambda) : RowPredicate(), callback_(lambda) {}
virtual bool evaluate(const QString& val) const override {return callback_(val);}
protected:
const StdPredicateLambda callback_;
};
The nasty effect of this is that whenever lambda is used, it must be wrapped into PredicateLambda
constructor:
myObject.deleteItems(std::make_shared<PredicateLambda>([]->bool{ ... lambda code ... }));
This is ugly. I have two options:
- for every function that accepts predicate, have an overload that does the conversion seen above. This duplicates number of methods in header file
Have an implicit conversion from
std::function<bool(const QString& val)>
tostd::shared_ptr<Predicate>
which would execute this:std::shared_ptr<Predicate> magicImplicitConversion(const StdPredicateLambda& lambdaFn) { return std::make_shared<PredicateLambda>(lambdaFn); }
I came here to ask whether the second option is possible. If it is, does it carry any risk?