Универсальный контейнер для хранения объектов определенного шаблона в Stack Overflow

Я пытаюсь создать универсальный контейнер, который может хранить гетерогенные объекты типа Wrapper< T> где T может быть любым определяемым пользователем типом. Я видел boost :: any и другие решения, но я не могу вызвать функцию foo () без перезаписи (я не знаю, какой тип перезаписать, информация о T теряется). Она возвращается к исходному типу.

Как я могу разумно реализовать универсальный контейнер / использовать существующий универсальный контейнер для достижения этой цели?

template <typename T>
class Wrapper{
public:
Wrapper(const T& a):o(a){};
Wrapper(){};
//public methods
void foo(){
//do stuff
};
private:
T o;
};

class X{};
class Y{};

int main(){
X x;
Y y;

A_GENERIC_CONTAINER generic_container;
// A_GENERIC_CONTAINER should be able to store
// any number of heterogeneous objects of type Wrapper<T>
// where T can be any user defined type.

generic_container.push_back(x);
generic_container.push_back(y);

auto it =  generic_container.begin();
auto end =  generic_container.end();
while(it != end){
it->foo();
++it;
}
}

3

Решение

Наиболее общий способ — создать базовый класс для Wrapper, скажем, BaseWrapper, и определить чисто виртуальные функции BaseWrapper, которые затем будут реализованы в каждом из классов Wrapper. Благодаря специализации каждый Wrapper, Wrapper, может иметь свою собственную реализацию. Сделав это, вы можете использовать контейнер с умным указателем на базовый тип и использовать его на досуге.

Есть несколько возможных ярлыков. Например, в простом случае в вашем примере, я бы рекомендовал использовать std::function, В этом помогает вспомогательная функция. Обратите внимание, что это действительно работает, только если вызывается только 1 метод. Я бы также порекомендовал определить вашу обертку operator() напрямую, чтобы вам не пришлось использовать привязку.

template<T>
std::function<void()> wrap(const T& x)
{
return std::bind(&Wrapper<T>::foo, Wrapper<T>(x));
}

int main(){
X x;
Y y;

std::vector<std::function<void()> > generic_container;
// A_GENERIC_CONTAINER should be able to store
// any number of heterogeneous objects of type Wrapper<T>
// where T can be any user defined type.

generic_container.push_back(wrap(x));
generic_container.push_back(wrap(y));

auto it =  generic_container.begin();
auto end =  generic_container.end();
while(it != end){
(*it)();
++it;
}
}

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

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

class Base
{
public:
virtual ~Base() {};
virtual void foo() = 0;
};

template <typename T>
class Wrapper : public Base{
public:
Wrapper(const T& a):o(a){};
Wrapper(){};
//public methods
virtual void foo(){
//do stuff
};
private:
T o;
};

int main(){
X x;
Y y;

std::vector<std::shared_ptr<Base> > generic_container;
// A_GENERIC_CONTAINER should be able to store
// any number of heterogeneous objects of type Wrapper<T>
// where T can be any user defined type.

generic_container.push_back(std::make_shared<Wrapper<X>>(x));
generic_container.push_back(std::make_shared<Wrapper<Y>>(y));

auto it =  generic_container.begin();
auto end =  generic_container.end();
while(it != end){
it->foo();
++it;
}
}
4

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

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

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