mercredi 22 décembre 2021

the best design for mapping enums to const classes

I have this example that works : I create an object that implements "PartInterface" for each value of the enum and add them in a map. But I don't find this satisfactory, because everything could be inferred at compile time rather than at runtime. Is there a more elegant way to do this in c++ 11? Another solution would be to build the "YearPart", "MonthPart" and "DayPart" objects at each call of the "get" function, but it seems to me less efficient...

#include <iostream>

#include <map>
#include <memory>

struct Date{
    int year;
    int month;
    int day;
};

class PartInterface{
public:
    virtual const std::string & getName()const=0;
    virtual int getValue(const Date& d)const=0;
    virtual ~PartInterface(){}
};

class Part : public PartInterface{
public:
    Part(const std::string& name):_name(name){}

    const std::string & getName()const{
        return _name;
    }
    virtual int getValue(const Date& d)const=0;
    
private:
    std::string _name;
};

class YearPart : public Part{
public:
    YearPart():Part("year"){}
    int getValue(const Date& d)const{
        return d.year;
    }
};

class MonthPart : public Part{
public:
    MonthPart():Part("month"){}
    int getValue(const Date& d)const{
        return d.month;
    }
};

class DayPart : public Part{
public:
    DayPart():Part("day"){}
    int getValue(const Date& d)const{
        return d.day;
    }
};

enum DatePart{
    Year,
    Month,
    Day
};

class Parts{
public:
    Parts(){
        _map[Year].reset(new YearPart());
        _map[Month].reset(new MonthPart());
        _map[Day].reset(new DayPart());
    };
    
    const PartInterface& get(const DatePart& date_part)const{
        return * (_map.find(date_part)->second);
    }
    
private:
    std::map<DatePart, std::unique_ptr<PartInterface> > _map;
};

int main() {
  Date d({2016, 7, 23});
  const Parts parts;
  std::cout << "Date " 
    << parts.get(Year).getValue(d) << " " 
    << parts.get(Month).getValue(d) << " " 
    << parts.get(Day).getValue(d) << std::endl;
  return 0;
}

Aucun commentaire:

Enregistrer un commentaire