Heath
Heath

Reputation: 123

Implementation of Specialized Templated Classes with Some Similar Features

I would like to implement a class design that achieves the following architecture:

I would like to instantiate classes that describe the object "ReadoutChip" of 4 different flavours, defined by the enumeration:

enum Flavour {F1, F2, F3, F4};

so that a class of a given flavour can be achieved like:

ReadoutChip<F1> Chip_1;

I have to specialize in some features of these flavour instantiations while keeping others the same. For example, all Chip objects (of all flavours) should have a private variable called Threshold; and I would like to have common public methods like GetThreshold(). However, these different flavours should have different attributes, which requires template specification. I have been unsuccessful in implementing something like this. Below is my attempt so far:

#include <iostream>

enum Flavour {F1, F2, F3, F4};
template <Flavour E, bool base = true> class ReadoutChip
{
        private:
                double Threshold = 1000;
        public:
                double GetThreshold();
};

template <> class ReadoutChip<Flavour::F1, true> : public ReadoutChip<Flavour::F1, false>
{
        public:
                ReadoutChip();
                ~ReadoutChip() = default;
                void SayHi();
};

ReadoutChip<Flavour::F1, true>::ReadoutChip() {std::cout << "Hi!" << std::endl;}

template <> double ReadoutChip<Flavour::F1, false>::GetThreshold() {return this->Threshold;}

int main()
{
        ReadoutChip<Flavour::F1> F_1;
        std::cout << F_1.GetThreshold() << std::endl;
        return 0;
}

This compiles successfully and somewhat gets the job done. Its only problems are that I have to copy the line:

template <> double ReadoutChip<Flavour::F1, false>::GetThreshold() {return this->Threshold;}

for each flavour, and apparently the line,

template <Flavour E> double ReadoutChip<E, true>::GetThreshold() {return this->Threshold;}

outputs a compilation error. Despite the partial success of this implementation, I would like to know if there is a way to achieve such a result without using the boolean variable base here, for the sake of C++ rigour.

Upvotes: 1

Views: 44

Answers (1)

WBuck
WBuck

Reputation: 5503

If I've understood the question correctly I think a better fit here would be inheritance.

Have all of your "chip" variants derive from a common base class. Stick all of your common code in the base class.

Take the example below, you can create as many "chip" variants as you'd like, just have them derive from your base class.

class readout_chip_base
{
public:
    readout_chip_base(double threshold) noexcept
        : threshold_{threshold}
    {}

    double get_threshold() const noexcept {
        return threshold_;
    }

    virtual void take_reading() = 0;
    virtual ~readout_chip_base() = default;

protected:
    void update_threshold(double threshold) noexcept {
        threshold_ = threshold;
    }
private:
    double threshold_;
};

class f1_readout_chip : public readout_chip_base
{
public:
    f1_readout_chip() noexcept
        : readout_chip_base{42.01}
    {}

    void take_reading() override {
        update_threshold(104.23);
    }
};

int main() 
{
    f1_readout_chip f1{};  
    std::cout << f1.get_threshold() << '\n';  

    f1.take_reading();
    std::cout << f1.get_threshold() << '\n';  
}

Upvotes: 1

Related Questions