2012-02-02 3 views
2

Я пытаюсь создать класс шаблона, который содержит статический список объектов, в котором есть только один. То, что я до сих пор работает, но дает мне копию «mylist» для каждого типа класса B. Как я могу изменить его, чтобы получить один «mylist» для всех экземпляров класса B независимо от параметров шаблона?Использование статических переменных с шаблонами

Это то, что я есть:

template <class T> class A { 
    ... 
}; 
template <class T> class B { 
    static list<A<T> > mylist; 
    ... 
}; 
template <class T> list< A<T> > B<T>::mylist; 

Заранее спасибо :)

+7

Вы принципиально неправильно понимаете шаблоны. Учитывая 'template класс Foo;', каждый экземпляр 'Foo ' для разных 'T' является совершенно другим типом_. Следовательно, если 'Foo <>' содержит статический член данных, каждый экземпляр 'Foo ' для разных 'T' будет содержать другой статический член данных. Чтобы иметь один элемент данных, который может содержать разные типы, посмотрите на [Boost.Variant] (http://www.boost.org/libs/variant/), если все типы известны заранее или [Boost.Any] (http: //www.boost.org/libs/any/) в противном случае. (Но на самом деле, ваш дизайн звучит очень сомнительно в первую очередь.) – ildjarn

+0

Вы после сингла? http://www.infernodevelopment.com/singleton-c – Joel

ответ

4

Как изменить его так, что у меня есть только одна копия

Вы можете наследовать от общий (не шаблонный) базовый класс, чтобы гарантировать, что для каждого экземпляра шаблона не существует экземпляра.

... который содержит любой тип?

Это зависит от ваших ожиданий. Я предположим из вашего примера, что «любой тип» означает «любое создание шаблона класса A».

Поскольку эти типы могут отличаться по размеру, вы будете делать все, чтобы удерживать указатели на объекты.

Это один пример решения, которое решило бы обе эти проблемы.

class ACommon { 
    // Put a common virtual interface here. 
}; 

template <class T> class A : public ACommon { 
}; 

class BCommon { 
    // You'll have a single, common static here. 

    static list<shared_ptr<ACommon> > mylist; 
}; 

template <class T> class B : public BCommon{ 

}; 
1

Вы не можете «просто» иметь ЛЮБОЙ тип в списке, живущий бок о бок. В зависимости от того, что вы ожидаете от этого списка, и объектов в нем, есть несколько вещей, которые нужно сделать.

Альтернативой решению Дрю было бы следующее: Вам обязательно нужен BCommon, если вам нужен один список для всех экземпляров. Если вы не хотите скрывать свои типы A за интерфейсом, вы можете использовать Boost :: any или Boost :: variant для хранения ваших объектов A.

+0

Да, 'boost :: any' и' boost :: variant' были бы полезны. Ницца. –

+0

'boost :: variant 'немного опасен для новичков; поскольку это объединение, он предполагает размер самого большого типа. Новичок, не заметив, мог потратить много памяти, просто чтобы сохранить один большой объект рядом с миллионным. 'boost :: any '- это совсем другая история. Хотя это не приведет к неопределенному поведению из-за неправильного перевода (например, void *), это может привести к сбою вашей программы «в поле» из-за необработанного «bad_cast_exception». ИМХО, для% 90 случаев, ваше решение - путь. – enobayram