Skip to content

Instantly share code, notes, and snippets.

@LordJZ
Last active December 10, 2015 14:58
Show Gist options
  • Select an option

  • Save LordJZ/4451246 to your computer and use it in GitHub Desktop.

Select an option

Save LordJZ/4451246 to your computer and use it in GitHub Desktop.
C++ Service Locator
#pragma once
#ifndef _a553_services_services_h
#define _a553_services_services_h
#include <a553/internals.h>
#include <a553/compiler.h>
#pragma region private details
#define _GET_SERVICE_FUNC(SERVICENAME) GetService_##SERVICENAME
#define _GET_SERVICE_RET(SERVICENAME) SERVICENAME*
#define _DEFINE_SERVICE(DECLSPEC, SERVICENAME, IMPLNAME, ...) \
a553_services_namespace_begin; \
DECLSPEC _GET_SERVICE_RET(SERVICENAME) \
_GET_SERVICE_FUNC(SERVICENAME)() \
{ \
static IMPLNAME s_service_##IMPLNAME = \
std::move(IMPLNAME(__VA_ARGS__)); \
return &s_service_##IMPLNAME; \
} \
a553_services_namespace_end
#define _REFERENCE_SERVICE(SERVICENAME) \
a553_services_namespace_begin; \
extern _GET_SERVICE_RET(SERVICENAME) \
_GET_SERVICE_FUNC(SERVICENAME)(); \
a553_services_namespace_end
#define _SERVICE(SERVICENAME) \
(a553_services_namespace _GET_SERVICE_FUNC(SERVICENAME)())
#pragma endregion
// Defines the specified service and exports it.
#define DEFINE_SERVICE_DLL(SERVICENAME, IMPLNAME, ...) \
_DEFINE_SERVICE(DLLEXPORT, SERVICENAME, IMPLNAME, __VA_ARGS__)
// Defines the specified service.
#define DEFINE_SERVICE(SERVICENAME, IMPLNAME, ...) \
_DEFINE_SERVICE(, SERVICENAME, IMPLNAME, __VA_ARGS__)
// References the specified service, allowing its usage.
#define REFERENCE_SERVICE(SERVICENAME) _REFERENCE_SERVICE(SERVICENAME)
// Ensures that the specified service is initialized.
#define INIT_SERVICE(SERVICENAME) ((void)(SERVICE(SERVICENAME)))
// Retrieves the specified service. The service must be referenced first.
#define SERVICE(SERVICENAME) _SERVICE(SERVICENAME)
#endif
#include "../testlib/testservice.h"
REFERENCE_SERVICE(TestService);
REFERENCE_SERVICE(DependentService);
int main()
{
INIT_SERVICE(TestService);
SERVICE(TestService)->DoSomething();
SERVICE(DependentService)->DoSomethingElse();
return 0;
}
#include <a553/services/services.h>
class NOVTABLE TestService
{
public:
// This method does something very, very important.
virtual void DoSomething() = 0;
};
class NOVTABLE DependentService
{
public:
virtual void DoSomethingElse() = 0;
};
#include <iostream>
#include "testservice_impl.h"
#ifdef BUILDING_DLL
DEFINE_SERVICE_DLL(TestService, TestServiceImpl);
DEFINE_SERVICE_DLL(DependentService, DependentServiceImpl, SERVICE(TestService));
#else
DEFINE_SERVICE(TestService, TestServiceImpl);
DEFINE_SERVICE(DependentService, DependentServiceImpl, SERVICE(TestService));
#endif
void TestServiceImpl::DoSomething()
{
std::cout << "void TestServiceImpl::DoSomething()" << std::endl;
}
void DependentServiceImpl::DoSomethingElse()
{
std::cout << "void DependentServiceImpl::DoSomethingElse()" << std::endl;
this->m_testService->DoSomething();
}
#include "testservice.h"
class TestServiceImpl : public TestService
{
public:
void DoSomething() override;
};
class DependentServiceImpl : public DependentService
{
TestService* m_testService;
public:
DependentServiceImpl(TestService* testService)
: m_testService(testService)
{
}
void DoSomethingElse() override;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment