0

I have a class that consists of an inner template class (iterator) with enumeration (RVSignalInfo::DataType) parameter and template function (getIterator) related to this inner class:

class ProviderSignalPlotCurve : public QObject
{
    // ...

    template <RVSignalInfo::DataType DT>
    class iterator
    {
        iterator(ProviderSignalPlotCurve* curve, quint64 begin, quint64 end) throw(WrongReadonlyPointerTypeException) {
            throw WrongReadonlyPointerTypeException();
        }
    };

    template<RVSignalInfo::DataType DT>
    inline iterator<DT> getIterator(quint64 begin, quint64 end) {
        return iterator<DT>(this, begin, end);
    }
};


template<>
class ProviderSignalPlotCurve::iterator < RVSignalInfo::DataType::Float >
{
public:

    iterator operator++() { ... }
    iterator operator++(int)  { ... }
    // ...

private:
    iterator(ProviderSignalPlotCurve* curve, quint64 begin, quint64 end)
        : m_curve(curve), m_index(begin)
    {
        // ...
    }
    // ...
};

template<>
class ProviderSignalPlotCurve::iterator < RVSignalInfo::DataType::Double >
{
public:

    iterator operator++() { ... }
    iterator operator++(int)  { ... }
    // ...

private:
    iterator(ProviderSignalPlotCurve* curve, quint64 begin, quint64 end)
        : m_curve(curve), m_index(begin)
    {
        // ...
    }
    // ...
};

// ...

Each enumeration member has its own specialization of template class.

If I try to create an instance of iterator, the compiler provides an the value of 'dataType' is not usable in a constant expression error. I guess it's because the template parameter has to be defined in runtime. Is there a way to deal with this problem?

RVSignalInfo::DataType dataType = curve->signalInfo()->dataType();
auto iterator = curve->getIterator<dataType>(visiblePartBegin, visiblePartEnd);

I found this workaround with switch statement, but it doesn't look convenient because it'll have to change the switch statement every time I add or remove an enumeration member. Is there more generalized way to deal with it?

Nikita
  • 337
  • 1
  • 3
  • 12
  • 1
    Templates are instantiated at compile time, so no. Unless you embed c++ compiler or interpreter into your app. – Slava Aug 15 '18 at 17:30
  • Are templates the right approach? Perhaps just a class with a subtype member variable set to the enumeration value? Enforce any needed type safety with type checks in member functions? – Dave S Aug 15 '18 at 18:06
  • @DaveS do you mean to create a subtype member and add its checking with `switch` into `getIterator` function? – Nikita Aug 15 '18 at 18:09
  • I mean to re-think why you need separate member functions for every enumeration type instead of shared functions that look at the type (stored or passed to the function) only when they need it. Generic shared code specialized only as needed. Your approach might be necessary based on the code we aren't shown, but in many cases it's overkill. – Dave S Aug 15 '18 at 18:16
  • As previously stated templates are resolved by the compiler at compile time. However, you can implement reflection in c++ to give you runtime flexiblity over class structure. – Mike Aug 15 '18 at 20:12
  • @DaveS all functions of `iterator` depends on the enumeration value so it's requires a lot of checks with `switch` into each function. Templates look good because we can use kind of different implementation of one class. – Nikita Aug 16 '18 at 04:16

0 Answers0