Реализация любого контейнера

Я хорошо знаю 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 с той разницей, что однажды объявленный тип может измениться.

Редактировать:

На самом деле, я хочу создать обертку вокруг std::basic_filebuf, Этот класс-оболочка открывает файл с char,wchar_t или же unsigned long на основе спецификации. Оболочка также получена из basic_filebuf с параметром шаблона, который выбирает клиент. Внутренне он преобразует кодовые точки Unicode из файла в желаемую кодировку клиента. Проблема возникает при хранении внутреннего basic_filebuf потому что он может быть объявлен с любым типом в качестве параметра шаблона. Я не хочу использовать специализацию шаблонов, потому что я хочу, чтобы клиент мог передавать свои собственные basic_filebuf пример.

Должен быть совместим с VS2010, который имеет ограниченные возможности из C ++ 11.

1

Решение

Это нельзя сочетать с проверкой типов во время компиляции. Основываясь на вашем «идеально» примере:

container c;
if (thingKnownAtRunTime()) {
c = vector<int>;
} else {
c = vector<string>;
}
c.push_back("hello world");

В случае с filebuf вы можете получить что-то вроде (предупреждение: не проверено)

template<typename FILEBUF>
void gensputc(FILEBUF* fb, long long c) {
FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c);
fb->sputc(c2);
}

class FileBufWrapper {
public:
template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) {
fb_ = fb;
sputc_ = gensputc<FILEBUF>;
}
void sputc(long long c) {
sputc_(fb_,c);
}
private:
typedef void(*sputc_t)(void*, long long);
sputc_t sputc_;
void* fb_;
};

Функция smart_convert генерирует исключение времени выполнения, если значение не может быть преобразовано в тип char. Кроме того, это необходимо сделать для каждой функции, которую вы собираетесь вызывать.

Если у вас есть доступ к std :: function и std :: bind в c ++ 11, это можно сделать немного чище, особенно в тех случаях, когда вам не нужно ничего преобразовывать.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]