0

I want to implement a base class with multiple children.

Base Class

    template <typename T>
    class Trigger
    {
    protected:
        T threshold;
        Trigger(T a_threshold) : threshold(std::pow(10, a_threshold / 20)){};
    public:
        void setThreshold(T a_threshold)
        {
            threshold = std::pow(10, a_threshold / 20);
        }
        virtual bool operator()(const T &first, const T &second) const;
        virtual ~Trigger() = default;
    };

Derived Class

    template <typename T>
    class ZeroCrossingRisingTrigger : public Trigger<T>
    {
    public:
        ZeroCrossingRisingTrigger(void) : Trigger<T>(0.){};

        bool operator()(const T &first, const T &second) const override
        {
            return (first <= 0) & (second > 0);
        }
    };

Usage in the main file

#include "Trigger.hpp"
int main([[maybe_unused]] int argc, [[maybe_unused]] char const *argv[])
{
    Trigger::ZeroCrossingRisingTrigger<double> trig;
    return 0;
}

But on I get the following error when I try to compile it:

(...): undefined reference to `Trigger::Trigger::operator()(double const&, double const&) const'

I don't understand why I get this error because I implemented the operator exactly as written in the error message.

4
  • 5
    it is not defined you just delared it Commented Nov 8, 2021 at 8:20
  • 3
    virtual and template don't mix very well together stackoverflow.com/questions/2354210/… Commented Nov 8, 2021 at 8:21
  • Thank you for your comments. Would you recommend to implement it using CRTP? Commented Nov 8, 2021 at 8:37
  • 1
    Either provide an implementation in the base class or make it pure (virtual bool operator()(const T &first, const T &second) const = 0;) Commented Nov 8, 2021 at 8:53

1 Answer 1

1

You have not defined an implementation for operator() for Trigger<T>. An option would be to make Trigger an abstract base class by making the operator member function a pure virtual function:

virtual bool operator()(const T &first, const T &second) const = 0;

Alternatively, you can provide an empty implementation.

On a side-note, in the constructor of ZeroCrossingRisingTrigger you pass 0.0 as an argument for the base class constructor. This sort of hints there is no need for ZeroCrossingRisingTrigger to be templated itself, unless you want to control the type of the 0.0 literal from the outside.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.