Я хорошо знаю boost::any
и boost::variant
, но в этом случае они не соответствуют моим потребностям.Реализация любого контейнера
Обычно, чтобы содержать объект неизвестного типа, можно получить его из общей базы и получить доступ к экземпляру с помощью виртуальных методов. Но что можно сделать, если невозможно использовать общую базу?
Я знаю, что в этом примере вам нужно будет знать тип, содержащийся в нем, но нести меня. std::vector
- это шаблонный класс с классом верхнего уровня, также являющийся шаблоном. Насколько мне известно, не может быть предоставлена база без шаблонов без изменения заголовков STL. Теперь давайте скажем, что я хочу создать вектор одного типа, но класс, содержащий класс, не заботится о типе, но он требует доступа к некоторым из «общих» методов, например size()
и pop_back()
.
Используя boost::any
, тип был удален, что делает невозможным разыменование содержащегося объекта. boost::variant
и tuple
требуют знать перед собой, какие типы могут быть вставлены, в результате чего содержащийся класс сам по себе является шаблоном.
То, что я до сих пор что-то вроде этого:
struct container
{
virtual ~container() = 0;
virtual void pop_back() = 0;
virtual size_t size() = 0;
...
}
template < typename T >
struct contained
{
std::vector<T> _vec;
contained (size_t n, T _what) : _vec(n, _what) {}
virtual void pop_back() { _vec.pop_back(); }
...
}
class some_class
{
container* _cont;
template < typename T >
void create (T _first) { _cont = new contained<T>(1,_first); }
...
}
Здесь клиент может позвонить по create()
и параметр шаблона должен определяться автоматически. Не очень хороший пример, который я знаю, но я пытаюсь скрыть параметры шаблона от клиента. Не делая этого, some_class
должен также отслеживать, какой тип хранится.
Мой метод основан на виртуальных вызовах, которые приводят к потере производительности, особенно если внутренний класс имеет свои собственные виртуальные методы.
Есть ли какие-либо другие типы контейнеров, которые лучше отвечали бы моим потребностям?
В идеале, я хотел бы что-то вроде этого
container = std::vector<T>;
container.pop_back();
container.push_back(T2); // compile error if types don't match
Где внутренне он будет отслеживать тип и сделать простой бросок, а не полагаться на виртуальные методы. Почти как auto
с той разницей, что после объявления его тип может измениться.
Edit:
В действительности, я хочу, чтобы создать оболочку вокруг std::basic_filebuf
. Этот класс-оболочка открывает файл с char
, wchar_t
или unsigned long
на основе спецификации. Обертка также получена из basic_filebuf
с параметром шаблона, который выбирается клиентом. Внутри он преобразует коды кодов Unicode из файла в желаемую кодировку клиентов. Проблема возникает при сохранении внутреннего basic_filebuf
, поскольку он может быть объявлен любым типом в качестве параметра шаблона. Я не хочу использовать специализированную специализацию, потому что хочу, чтобы клиент мог передать свой собственный экземпляр basic_filebuf
.
Должно быть совместимо с VS2010, которое имеет ограниченные возможности от C++ 11.
Какая проблема вы пытаетесь решить, где именно это нужно? – GManNickG
@GManNickG В качестве примера можно привести стандартные классы потоков, в которых тип элемента может быть 'char'' wchar_t' 'int' ... Как бы вы сохранили этот шаблон без заботы о внутреннем типе? Как насчет 'std :: string' и' std :: wstring'? Почти идентичны, но требуют немного другой обработки. – Twifty
Извините, я не следую. Я имею в виду, что ваша программа будет в конечном итоге * делать *? – GManNickG