/******************************************************************************
Online C++ Compiler.
Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <iostream>
#include <new>
using namespace std;
class RomObject
{
public:
constexpr RomObject() {}
};
template<typename T,
class Enable = void>
class Singleton
{
public:
Singleton(const Singleton&) = delete;
Singleton& operator = (const Singleton&) = delete;
static T& GetInstance()
{
if(!bCreated)
{
bCreated = true;
new (&placeholder) T;
}
return *(reinterpret_cast<T*>(&placeholder));
}
constexpr static void* GetPlaceholder()
{
constexpr void* result = static_cast<void*>(&placeholder) ;
return result ;
}
static const std::string& where()
{
static std::string me = "RAM";
return me;
}
protected:
Singleton() {};
static bool bCreated;
static typename std::aligned_storage<sizeof(T), alignof(T)>::type placeholder;
};
template<typename T>
class Singleton<T, typename std::enable_if_t<std::is_base_of<RomObject, T>::value>>
{
public:
Singleton(const Singleton&) = delete;
Singleton& operator = (const Singleton&) = delete;
static constexpr const T& GetInstance()
{
return instance;
}
constexpr static const T* GetPlaceholder()
{
return &instance;
}
static const std::string& where()
{
static std::string me = "ROM";
return me;
}
protected:
constexpr Singleton() { };
static constexpr T instance = T();
};
template<typename T, class Enable>
bool Singleton<T, Enable>::bCreated = false;
template<typename T, class Enable>
typename std::aligned_storage<sizeof(T), alignof(T)>::type Singleton<T, Enable>::placeholder;
template<typename T>
constexpr T Singleton<T, typename std::enable_if_t<std::is_base_of<RomObject, T>::value>>::instance;
//? ??? ???? ??? const ?????? constexpr - ?? ?? ????? ?????? ?????????? ???? T ?? constexpr (?.?. ????? ??????? ? RAM ? ????????? ???????????? ?????????????)
/*template<typename T>
const T Singleton<T, typename std::enable_if_t<std::is_base_of<RomObject, T>::value>>::instance; */
class IA
{
public:
virtual int Get() const = 0;
};
class B
{
friend class Singleton<B>;
public:
B() : b(23) {};
int GetB() const
{
return b;
};
void setB(int v)
{
b = v;
}
int b;
};
class C : public RomObject
{
public:
int d;
constexpr C() : d(6) {};
//C() : d(3) {};
};
class D //: public RomObject
{
public:
int d;
//constexpr D() : d(6) {};
//D() : d(6) {};
};
class A : public RomObject, public IA
{
friend class Singleton<A>;
public:
int Get() const override
{
return test.GetB();
}
void set(int v)
{
test.setB(v);
}
private:
B& test; //—????? ?? ?????? ??????? ????? ? RAM ????? ???? ??? const
const C& test2; //? ??? ?????? ?? ROM ??????? ??¤???? ???? const, ? ????????? ?????? ?????? ??????¤???
constexpr A() :
test(*static_cast<B*>(Singleton<B>::GetPlaceholder()))
,test2(Singleton<C>::GetInstance())
{
}
};
int main()
{
//std::cout << Test::myVar << std::endl;
const A& test1 = Singleton<A>::GetInstance();
//??????? ?????? ?????? B ????? ????? ??? ??? ???????? A, ?????????? ?????? ?? ????, ???????? ? ????
const B& test2 = Singleton<B>::GetInstance();
const C& test3 = Singleton<C>::GetInstance();
cout<<"Get result: "<<test1.Get()<<std::endl;
cout<<"Singleton<A> - "<<Singleton<A>::where().data()<<std::endl;
cout<<"Singleton<B> - "<<Singleton<B>::where().data()<<std::endl;
cout<<"Singleton<C> - "<<Singleton<C>::where().data()<<std::endl;
cout<<"Singleton<D> - "<<Singleton<D>::where().data()<<std::endl;
cout<<"Singleton<A> - "<<Singleton<A>::GetPlaceholder()<<std::endl;
cout<<"Singleton<B> - "<<Singleton<B>::GetPlaceholder()<<std::endl;
cout<<"Singleton<C> - "<<Singleton<C>::GetPlaceholder()<<std::endl;
cout<<"Singleton<D> - "<<Singleton<D>::GetPlaceholder()<<std::endl;
cout<<"test1 - "<<&test1<<std::endl;
return 0;
}