0

I have a templated class with a constructor which takes a single argument; a function pointer to a function that takes an argument of the second template-type. and returns an element of the first template-type.

Here's the code:

cache_controller.hpp:

template<class TYPE, class KEY>
class cache
{
    private:
        TYPE (*create_func)(KEY);
    public:
        cache(TYPE (*func)(KEY));
};

extern sf::Texture * create_texture(std::string path);

cache_controller.cpp:

template<class TYPE, class KEY>
cache<TYPE, KEY>::cache(TYPE (*func)(KEY))
{
    this->create_func = func;
}

sf::Texture * create_texture(std::string path)
{
    sf::Texture * tex_p = new sf::Texture;
    tex_p->loadFromFile(path);
    return tex_p;
}

Test code:

cache<sf::Texture *, std::string> tcache(&create_texture);

However, when I link I get this error:

[Linker error] main.cpp:11: undefined reference to `cache<sf::Texture*, std::string>::cache(sf::Texture* (*)(std::string))' 

Of course, if there are any easier ways to implement an object cache with arbitary keys, values and creation functions I'm all ears.

Mloc
  • 115
  • 1
  • 9
  • Note that it is more common to put the template parameters the other way around, analogous to `std::map` or other associative containers: `cache` (key => value) – leemes Feb 09 '13 at 14:05

2 Answers2

3

You provide a definition for member functions of a template class in a .cpp file.

The definition of those member functions must be visible to the compiler at the instantiation point (i.e., from the .cpp file that invokes those functions), otherwise only their declaration will be seen, and the compiler will just rely on that function being defined somewhere else, while processing a different translation unit.

Since there is no instantiation of that function in the translation unit (i.e. .cpp file) where its definition is visible to the compiler, none will be generated, and the linker will eventually complain that no definition is provided.

You should put the definition of cache's constructor in the header file where class template cache is defined (which is, in your case, cache_controller.hpp).

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
2

The implementation of a templated method must coincide with the file that holds its declaration. Template instantiation is a compile-time operation, not a link-time. Merge the two into each other for the linker error to be resolved. That is, implement the constructor either inside the class or outside but within the same file.

David G
  • 94,763
  • 41
  • 167
  • 253