mardi 2 août 2016

Can I define implicit cast from std::function to std::shared_ptr

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)> to std::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?

Aucun commentaire:

Enregistrer un commentaire