Как обобщить контейнерные адаптеры с помощью шаблонов?
У меня есть следующий класс:
#include <set>
#include <stack>
#include <queue>
#include <string>
template <typename T>
class MySet
{
public:
const std::stack<T> data() const
{
std::stack<T> other_cont ( typename std::stack<T>::container_type ( cont.begin(), cont.end() ) );
return other_cont;
}
private:
std::set<T> cont;
};
И следующий код:
MySet<std::string> a;
MySet<int> b;
const std::stack<std::string> s = a.data();
const std::queue<int> q = b.data();
Я хотел бы использовать одну шаблонную функцию-член для инициализации любого типа адаптера. Пока это работает только с stack
или же queue
Я не могу понять, как использовать шаблоны для его обобщения.
Вот что я попробовал:
template <template <typename> typename M>
const M<T> data() const
{
M<T> other_cont ( typename M<T>::container_type ( cont.begin(), cont.end() ) );
return other_cont;
}
Компилятор говорит, что не может вывести параметр шаблона M
,
2 ответа
Рассмотрим ваш телефонный код:
a.data()
Здесь нет ничего для data()
вывести его тип возвращаемого значения. Вы должны уточнить это явно, что-то вроде:
a.data<std::stack>()
Но из ваших комментариев вы не можете редактировать код использования. Что вы можете сделать, это использовать оператор преобразования типа шаблона:
template <typename M>
operator M() const
{
M other_cont ( typename M::container_type ( cont.begin(), cont.end() ) );
return other_cont;
}
Чтобы сохранить код неотредактированным, ваш data
Метод должен вернуть этот объект:
const MySet<T> data() const
{
return *this;
}
Простой подход заключается в использовании оператора преобразования:
#include <set>
#include <stack>
#include <queue>
#include <string>
template <typename T>
class MySet
{
public:
template <typename O, typename = typename O::container_type>
operator O() const
{
return O(typename O::container_type(cont.begin(), cont.end()));
}
private:
std::set<T> cont;
};
Используя этот подход, обозначения отличаются, хотя: нет data()
член используется:
int main()
{
MySet<std::string> s;
std::stack<std::string> st = s;
std::queue<std::string> qu = s;
}
Если вы хотите использовать data()
член и получить различные типы из результата, вам нужно вернуть прокси, который соответствующим образом конвертируется при доступе:
#include <set>
#include <stack>
#include <queue>
#include <string>
template <typename T>
class MySet
{
public:
class Proxy {
std::set<T> const* set;
public:
Proxy(std::set<T> const* s): set(s) {}
template <typename O, typename = typename O::container_type>
operator O() const
{
return O(typename O::container_type(set->begin(), set->end()));
}
};
Proxy data() const { return Proxy{&this->cont}; }
private:
std::set<T> cont;
};
int main()
{
MySet<std::string> s;
std::stack<std::string> st = s.data();
std::queue<std::string> qu = s.data();
}