0

I have a class that generalizes SISO functions:

template<typename T, typename S> struct Function {
    virtual S operator()(const T& value) const = 0;

Then I have a bunch of subclasses of a BinaryOperator class:

template<typename T, typename S> struct BinaryOp : public Function<T, S> {
    Function<T, S>& funcA;
    Function<T, S>& funcB;
    ...
}

template<typename T, typename S> struct Addition : public BinaryOp<T, S> {
    virtual inline S operator()(const T& value) const {
        return funcA(value) + funcB(value);
    }
};

After these I can finally implement the operators used to add, multiply, etc. the functions together. So these build an AST, memory management for later.

inline Addition<T, S>& operator+(Function<T, S>& func) {
    return *new Addition<T, S>(*this, func);
}
inline Addition<T, S>& operator+(const T& ref) {
    return *new Addition<T, S>(*this, *new Const<T>(ref));
}
...

I also implement common functions (sine, cosine, etc.):

template<typename T> struct Sine : public Function<T, T> {
    virtual inline T operator()(const T& value) const {
        return std::sin(value);
    }
};

The problem appears once I want to implement nested functions [f(g(x))].

template<typename U> inline Inclusion<T, S, U> operator()(Function<U, S>& func) {
    return *new Inclusion<T, S, U>(*this, func);
}

I tried to use this operator using this sketch but failed. According to VS it cannot convert Cosine[T = float] to const float&. So it seems like it's trying to use the first implementation of the operator().

Sine<float> sine = Sine<float>();
Cosine<float> cos = Cosine<float>();
Function<float, float>& func = sine(cos);

If I don't use the operator() but give it some random name it works. Can anyone tell me why? Or better how can I make this work while keeping the templates and operator overloading?

The line generating the error:

Function<float, float>& func = sine(cos);

And the errors:

function "System::Math::Sine<T>::operator() [with T=float]" cannot be called with the given argument list, argument types are: (System::Math::Cosine<float>)
            object type is: System::Math::Sine<float>

'float System::Math::Sine<float>::operator ()(const T &) const': cannot convert argument 1 from 'System::Math::Cosine<float>' to 'const float &'    
Balázs Eszes
  • 166
  • 1
  • 6
  • Could you please clarify what line in your code that is generating the error, and show the compiler error. – super Mar 04 '18 at 00:21
  • You can try to specify template arguments directly like sine.operator()(cos). Does it work? – Paweł Stankowski Mar 04 '18 at 00:27
  • Added more detailed error message. Template specialization is actually what I want to avoid. I am sure defining the operator that implements sin(cos) would work but the goal is to generalize trivial operations like addition, subtraction, nesting for all possible functions and all possible types. – Balázs Eszes Mar 04 '18 at 00:47
  • 1
    You are leaking memory everywhere, stop writing `new` and `&`. You declared `sine` to only take `const float&` as argument, you can't call it with anything else – Passer By Mar 04 '18 at 02:21
  • Consider reading a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Passer By Mar 04 '18 at 02:23

0 Answers0