Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to design a class that is constant after initialization and exists only once in my whole program

I'm pretty sure that the following question already has a good answer somewhere else, but it's difficult to find since I do not know the "name" of my problem.

I'm designing a class/object/"something" with the following properties:

  • It is sort of a lookup table.
  • It does not change after initialization.
  • It has several non-primitive members.
  • It has a complicated initializer function.
  • It is the same for the whole program.
  • It is parametrized by template parameters.

So this sounds like a static template class:

template <int T>
class LookupTable{

  public:
    static void init(){
      // create entries depending on T
    }

  private:
    static vector<Entries> entries;

}

What I dislike is that I need to call init() somewhere in my program. So the first question is: How can I make this class fully self-contained, with no need to be explicitly initialized somewhere?

Second part: What is the general design approach to implement such a class? I would be perfectly happy with a link to a good example.

A possible candidate is the singleton. But I have some doubts: - The singleton considered bad design in many cases. Is it fine for a lookup table as described? - Singleton is somewhat long notation, since I have to use LookupTable::getInstance()->getEntry(idx).

like image 994
Michael Avatar asked May 06 '15 11:05

Michael


People also ask

Which variables can only be initialized with a constant?

In C, static variables can only be initialized using constant literals.

How are constant data members of a class initialized?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class. The list of members, that will be initialized, will be present after the constructor after colon. members will be separated using comma.

Can we initialize a class member variable as soon as the same is defined?

The constructors should be used to initialize member variables of the class because member variables cannot be declared or defined in a single statement. Therefore, constructors are used in initializing data members of a class when an object is created.

Can a class contain an instance of itself?

A class declaration can contain static object of self type, it can also have pointer to self type, but it cannot have a non-static object of self type.


1 Answers

Singleton is the pattern, but use the safer variant where this approach avoids static initialization order fiasco and thread race conditions and since you complained about the length - we can shorten it a bit further passing the indices through the get_entry function:

template <int T>
class LookupTable{
    public:
    static std::vector<Entry> make_entries(){ ...}
    static const std::vector<Entry>& get_entries(){
        static const std::vector<Entry> instances = make_entries();
        return instances;
    }
    static const Entry& get_entry(size_t idx){
        return get_entries()[idx];
    }
};

Another approach that avoids all the evils of a singleton are not to use a singleton - just pass a regular old class in directly as just another parameter. I do this with many crc function implementations with relatively heavy tables... most stuff won't care and then you don't have to wig out on design patterns. And it's faster.

like image 51
Jason Newton Avatar answered Nov 14 '22 19:11

Jason Newton