Если вы хотите вставить большой кодовый блок с необязательными номерами строк и т. Д., Используйте макрос макросов (доступно в разделе Макросы -> Другое).
Вы всегда можете сделать что-то вроде этого:
class IFoo {};
class Foo : public IFoo {};
template <typename T>
class Singleton
{
// ..
};
typedef Singleton<Foo> FooSingleton;
int main()
{
FooSingleton::Instance()->foo();
return 0;
}
Раздражающий мета-ответ: «Почему вы используете синглтон?» Мне еще предстоит найти ситуацию, когда вам действительно нужно его использовать. ИМХО, его недостатки перевешивают его достоинства, в реальных жизненных ситуациях.
Возможно, вам понадобится что-то вроде 'boost :: noncopyable'.
Вы не можете этого сделать. IFoo - это интерфейс по дизайну и определению. Таким образом, количество экземпляров равно 0. С другой стороны, определение одноэлементного класса состоит в том, что у вас есть 1 экземпляр. 0! = 1.
Я думаю, что лучшим решением было бы ввести здесь фабричный класс или метод. Только представьте себе следующее:
struct FooCreator
{
typedef IFoo* result_type;
result_type operator()()const
{
return new Foo;
}
};
template<class Factory>
struct Singleton
{
static typename Factory::result_type instance()
{
if(instance_==typename Factory::result_type())
instance_ = Factory()();
return instance_;
}
private:
Singleton(){};
static typename Factory::result_type instance_;
};
template<class F>
typename F::result_type Singleton<F>::instance_ = typename F::result_type();
С уважением,
Ованес
Мне пришлось сделать что-то подобное, чтобы добавить модульные тесты в некоторый устаревший код. Мне пришлось заменить существующий синглтон, в котором использовался шаблон. Я дал два параметра одноэлементному шаблону, первый - это интерфейс, а второй - реализация.
Однако мне также пришлось добавить метод setTestInstance
, чтобы позволить модульным тестам переопределить экземпляр во время выполнения.
template <typename IfaceT, typename ImplT>
class Singleton
{
public:
static IfaceT* Instance() {
if (m_instance == NULL) {
m_instance = new ImplT();
}
return m_instance;
}
// Only used for unit tests
// Takes ownership of instance
static void setTestInstance(IfaceT* instace) {
m_instance = instance;
}
private:
static IfaceT * m_instance;
};
В этом случае setTestInstance
должен использовать std: : auto_ptr
и m_instance
должны быть boost :: scoped_ptr
. Чтобы избежать утечки памяти.
Взгляните на это так: в вашей программе нет ничего, что могло бы сообщить компилятору, какую реализацию интерфейса IFoo он должен создавать. Помните, что помимо Foo могут быть и другие реализации.
Если вы хотите использовать класс через интерфейс и определить, какая фактическая реализация должна использоваться где-то еще, взгляните на шаблон Abstract Factory .
Вы бы хотели использовать что-то вроде
IFoo my_foo = Singleton<Foo>::Instance();
my_foo->foo();
В основном вам нужно будет создать экземпляр шаблона Singleton, используя конкретный класс (в данном случае ваш класс Foo), и, учитывая, что ваш Foo является производным от IFoo, вы можете ссылаться на него через базовый указатель. Вы не можете напрямую создать экземпляр шаблона, используя неполный или абстрактный класс.