1

I'm dealing with a design dilemma and would appreciate your thoughts. I have implemented a template class PacketManager which implements the functionality of a resource manager for different types of packets given as a template. For every TYPE of packet, I have just one instance (singleton) and I want to have a counter to count the number of PacketManager instances generated for different types of packet (so essentially count the number of packet types in the system). Naturally for that, one would use a static int variable and increment it for every instantiation. However for templates I can't have just one static variables for all template instances. Instead I have one static variable per packet type. Can you guys think of a clean solution where I can get the functionality I need? Only solution comes to my mind is to have a global variable defined which is not ideal.

0

2 Answers 2

2

This is a false premise:

However for templates I can't have just one static variables for all template instances.

Yes you can:

#include <iostream>

struct Base {
    static int counter;
    Base() { counter++; }
};

int Base::counter = 0;

template <typename T> 
struct Foo : Base {};

int main(int argc, char** argv) {
    Foo<int> x;
    Foo<double> y;
    Foo<float> z;
    std::cout << Base::counter;
}

Output:

3

Actually this isn't something specific to your current problem. In general anything not depending on the template parameter can be moved to a non-template base class.

Sign up to request clarification or add additional context in comments.

2 Comments

This is brilliant. This solution didn't occur to me at all.
@Amir thats why I mentioned it in the end. You seem to miss that only stuff that depends on the template parameter needs to be part of the template. Moving everything else to a non-template base class can make things much simpler quite often (consider eg specializing the class template, then you only need to specialize members of the template, but not those of the base)
1

Instead of a global variable, you could scope it inside of another function:

size_t get_or_increment_counter(bool inc) {
    static size_t counter = 0;
    if (inc) counter++;
    return counter;
}

which your templated function would call:

template <typename T>
class PacketManager {
private:
    std::shared_ptr<T> construct() {
        get_or_increment_counter(true);
        return std::make_shared(...);
    }
public:
    T& get_instance() {
        static std::shared_ptr<T> ptr = construct();
        return *ptr;
    }
};

2 Comments

Thanks for this. The function should be in a global scope, and not a member function of the same template class. Is that correct?
That’s right, if it were in the same class then it’d be the same issue you’re seeing now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.