Search code examples
c++templatesreturn-typetrailing-return-type

returntype depending on template argument type


So I'm trying to write an algorithmic derivator, to derivate/evaluate simple polynomials. My Expression Logic is as follows: there are Constants and Variables, combined in to either a multiply or add Expression. In my Expression Class i have the method derivative which should return different Expressions depending wheter the Expression is an add or a multiply. here is my code:

enum OP_enum {Add, Multiply};

//********

template<typename T>
class Constant {
public:
    Constant(const T & v) : val_(v) {}
    T operator()(const T &) const {
        return val_;
    }
    Constant<T> derivative(){
        return Constant<T>(0);
    }
private:
    T val_;
};

//********

template <typename T>
class Variable {
public:
    T operator()(const T & x) const {
        return x;
    }
    Constant<T> derivative(){
        return constant(1);
    }
};

//********

template<typename L, typename R, OP_enum op>
class Expression {
public:
    Expression(const L & l, const R & r) : l_(l), r_(r) { }


    template <typename T>
    T operator()(const T & x) const {
        switch (op) {
            case Add:
                return l_(x) + r_(x);
            case Multiply:
                return l_(x) * r_(x);
        }
    }

    /*RETURN TYPE*/ derivative() {
        switch (op) {
            case Add:
                return l_.derivative() + r_.derivative();
            case Multiply:
                return l_.derivative() * r_ + l_ * r_.derivative();
        }
    }

private:
    L l_;
    R r_;
};

//********


template<typename L, typename R>
Expression<L, R, Add> operator*(const L & l, const R & r) {
    return Expression<L, R, Add>(l, r);
}

template<typename L, typename R>
Expression<L, R, Multiply> operator+(const L & l, const R & r) {
    return Expression<L, R, Multiply>(l, r);
}

is there a way i can specify the RETURN TYPE nicely? (it should be

Expression<RETURN TYPE of derivation called on L, RETURN TYPE of derivation called on R, Add>
Expression<Expression<RETURN TYPE of derivation called on L, R, Multiply>, Expression<L, RETURN TYPE of derivation called on R, Multiply>, Add>

depending if a sum or product is beeing derivated)

i have tried std::conditional and several things with decltype


Solution

  • auto derivative() {
        if constexpr (op == Ad)
            return l_.derivative() + r_.derivative();
        else if constexpr (op == Multiply)
            return l_.derivative() * r_ + l_ * r_.derivative();
    }
    

    The if constexpr is required if the branches deduce to different types.