Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheriting from a template class in c++ with enum as template parameter

I have some equal classes that contain enum with named constants (like Parts below) and text description for constants (like Parts but strings). Each source class looks like union (not c++ union :-) ) of two classes below. Want to remove code redundancy and got something like this for now:

template<class T> class SomeBaseClass
{
public:
    std::string toString()
    {
        uint32_t pairsNum = pairs.size();
        for (uint32_t i = 0; i < pairsNum; i++)
            if (pairs[i].first == name) {
                return pairs[i].second;
            }
        // exception will be here
        return std::string("");
    }
    void fromString(std::string name)
    {
        uint32_t pairsNum = pairs.size();
        for (uint32_t i = 0; i < pairsNum; i++)
            if (pairs[i].second == name) {
                this->name = pairs[i].first;
                return;
            }
        throw std::invalid_argument(name);
    }
    T get()
    {
        return name;
    }
    void set(T name)
    {
        this->name = name;
    }
private:
    T name;
    std::vector<std::pair<T, std::string> > pairs;
};

class Child: public SomeBaseClass<Child::Parts>
{
public:
    enum Parts { head, rightLeg, leftLeg, rightHand, leftHand, body };
    Child()
    { 
        /* filling SomeBaseClass::pairs by values will be here */
    }
};

But Child::Parts is nested type and not a user type for c++98 (can't use more than c++98 standard for this program) so compiler gives error (as expected). I don't want move out Parts from Child because it part of Child ideologically. Is there a beauty way to solve this situation?

like image 546
huan-kun Avatar asked Dec 10 '25 15:12

huan-kun


1 Answers

I don't want move out Parts from Child because it part of Child ideologically

This doesn't mean it has to be stored right inside the Child class itself. What you want to accomplish is impossible like that, C++98 or not. The common approach is to use traits:

template <typename>
struct Child_traits;

class Child;

template <>
struct Child_traits<Child> {
   enum Parts { head, rightLeg, leftLeg, rightHand, leftHand, body };
};

template <typename T>
class SomeBaseClass {
   typedef typename Child_traits<T>::Parts Parts;

   // use Parts type
};

class Child : public SomeBaseClass<Child> { 
    typedef Child_traits<Child>::Parts Parts; // get the parts type to the child
};

The bond between Child and Parts is established by template specialization (also available in C++98): the Child type acts as a key to the right specialization containing the correct Parts type.

like image 162
Jodocus Avatar answered Dec 13 '25 06:12

Jodocus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!