Pins
Pins

Reputation: 217

How to initialize a static member variable in class with template functions

As far as I found, there were articles about initializing a static variables in class templates. However, I´m using a normal class with member function templates, so I have to ask.

In short version(not whole class definition) I have a class that look like this:

class BatchManager
{
    private:

        static std::vector<BaseBatch_P> _BATCHES;

    public:

        template <class T>
        static void placeData(T* data){

            //Loop through the entire container
            for (auto&& b: _BATCHES)
                if (b==data){
                    dynamic_cast<Batch<T>>(b)->draw(data);
                }

            //If no bach found, create a new One
            createNewBatch(data);
        }
};

However, when I want to access the member variables inside the function, it shows: undefined reference to BatchManager::_BATCHES

Then I´ve tried the following: keep definition in class header :

 //BatchManager.h

 template <typename T>
 static void placeData(T* data);

And cpp file:

std::map<GLuint,BaseBatch_P> BatchManager::_TEXTURE_MAP;

template <typename T>
void BatchManager::placeData(T* data){

    //Loop through the entire container
    for (auto&& b: _BATCHES)
        if (b==data){
            dynamic_cast<Batch<T>>(b)->draw(data);
        }

    //If no bach found, create a new One
    createNewBatch(data);
}

It fixes the first problem, but then another appears, and it happens when I want to call my static function from the program:

BatchManager::render(_data);

Error message looks like this:

undefined reference to BatchManager::placeData<DataType>(DataType*)

How can i fix this problem? Or am I doing something wrong?

Upvotes: 0

Views: 360

Answers (1)

Richard Hodges
Richard Hodges

Reputation: 69854

Something like this:

#include <vector>
#include <typeinfo>

struct BaseBatch {

    virtual const std::type_info& get_type() const = 0;
    virtual ~BaseBatch() = default;
};

template<class T>
struct Batch : BaseBatch
{

    const std::type_info& get_type() const override
    {
        return typeid(T);
    }

    void draw(T* data) {}
};

using BaseBatch_P = BaseBatch*;

class BatchManager
{
private:

    static std::vector<BaseBatch_P>& get_batches() {
        static std::vector<BaseBatch_P> _;
        return _;
    }

public:

    template <class T>
    static void placeData(T* data){

        //Loop through the entire container
        bool found = false;
        for (auto&& b: get_batches())
            if (b->get_type() == typeid(T)) {
                dynamic_cast<Batch<T>*>(b)->draw(data);
                found = true;
            }

        //If no bach found, create a new One
        if (not found) {
            get_batches().push_back(new Batch<T>);
        }
    }
};

Upvotes: 1

Related Questions