3

I've been trying to implement the Service Locator pattern using a templated base class and inheriting from it:

    // Header File
    namespace one {
    template <class I, class N>
    class Locator {
    public:
        static void initialize() {
            service = &nullService;
        }
        static void provide(I* newService) {
            if (newService == 0) {
                initialize();
            } else {
                service = newService;

        }
        static I& get() { return *service; }
        virtual ~Locator() {
            if (service != &nullService) {
                delete service;
            }
    private:
        Locator();
        static I* service;
        static N nullService;
    };
    }

    // Source File
    #include "Locator.hpp"

    namespace one {
    template<class I, class N>
    I* Locator<I, N>::service;

    template<class I, class N>
    N Locator<I, N>::nullService;
    }

class I is the instance class, and class N is the null service class. And for the derived class:

    // Header File
    namespace two {
    class ExampleLocator : public one::Locator<Service, NullService> {}
    }

    // Source File
    namespace one {
    template class Locator<Service, NullService>;
    }

When I try and use this implementation,

    int main(int argc, char const *argv[]) {
        two::ExampleLocator::initialize();
        two::ExampleLocator::get().doSomething();
    }

gcc fails compiling with the following errors:

  • undefined reference to one::Locator::initialize()
  • in function one::Locator::get(): undefined reference to one::Locator::service

What am I doing wrong?

NOTE: I could get the project to compile by re-declaring Locator's static properties in the Derived class's cpp:

    // Alternative Derived class Source file
    namespace one {
    template<class I, class N>
    I* Locator<I, N>::service;

    template<class I, class N>
    N Locator<I, N>::nullService;

    template class Locator<Service, NullService>;
    }

NOTE2: the Derived class is in a different namespace than the Locator class.

Juan Pablo
  • 593
  • 1
  • 6
  • 12

1 Answers1

5

Template definitions must be visible in all translation units that use them. Move your code in the .cpp file to your .hpp file.

See: Why can templates only be implemented in the header file?

Community
  • 1
  • 1
Pubby
  • 51,882
  • 13
  • 139
  • 180