以下代码表示基于std :: vector的容器
template <typename Item>
struct TList
{
typedef std::vector <Item> Type;
};
template <typename Item>
class List
{
private
typename TList <Item>::Type items;
....
}
int main()
{
List <Object> list;
}
Run Code Online (Sandbox Code Playgroud)
是否可以模板化std :: vector并创建一个通用的容器,类似的东西?
template <typename Item, typename stl_container>
struct TList
{
typedef stl_container<Item>;
};
Run Code Online (Sandbox Code Playgroud)
stl_container表示std :: vector,std :: list,std :: set ...?我想在创建时选择容器的类型.
List <Object, std::vector> list; //vector of objects, not a real code
List <Object, std::vector> list; //list of objects, not a real code
Run Code Online (Sandbox Code Playgroud)
谢谢你的回答......
更新的问题:
我尝试了以下代码,但有错误:
#include <vector>
template <typename Item, typename Container>
struct TList
{
typedef typename Container <Item>::type type; //Error C2059: syntax error : '<', Error C2238: unexpected token(s) preceding ';
};
template <typename T>
struct vector_container
{
typedef std::vector<T> type;
};
int _tmain(int argc, _TCHAR* argv[])
{
TList <int, vector_container> v;
TList <int, map_container> m;
}
Run Code Online (Sandbox Code Playgroud)
GMa*_*ckG 11
是的,但不是直接:
template <typename Item, template <typename> class Container>
struct TList
{
typedef typename Container<Item>::type type;
};
Run Code Online (Sandbox Code Playgroud)
然后,您可以定义不同的容器策略:
template <typename T>
struct vector_container
{
typedef std::vector<T> type;
};
template <typename T>
struct map_container
{
typedef std::map<T, std::string> type;
};
TList<int, vector_container> v;
TList<int, map_container> m;
Run Code Online (Sandbox Code Playgroud)
但是有点冗长.*要直接做事,你需要采取詹姆斯描述的路线,但正如他所指出的那样,这最终是非常不灵活的.
但是,使用C++ 0x,我们可以做到这一点:
#include <map>
#include <vector>
template <typename Item,
template <typename...> class Container, typename... Args>
struct TList
{
// Args lets the user specify additional explicit template arguments
Container<Item, Args...> storage;
};
int main()
{
TList<int, std::vector> v;
TList<int, std::map, float> m;
}
Run Code Online (Sandbox Code Playgroud)
完善.不幸的是,除了通过如上所述引入的间接策略类之外,没有办法在C++ 03中重现这一点.
*我想强调一点,"有点啰嗦",我的意思是"这是非正统的".Jerry解释说,正确解决问题的方法就是标准库所做的事情.您只需让容器适配器的用户直接指定整个容器类型:
template <typename Item, typename Container = std::vector<Item>>
struct TList
{};
Run Code Online (Sandbox Code Playgroud)
但是,这留下了很大的问题:如果我不想容器的值类型为Item
,但something_else<Item>
?换句话说,如何将现有容器的值类型更改为其他容器?在你的情况下,你没有,所以不要再读,但在我们这样做的情况下,我们想重新绑定一个容器.
对我们来说不幸的是,虽然分配器执行以下操作,但容器没有此功能:
template <typename T>
struct allocator
{
template <typename U>
struct rebind
{
typedef allocator<U> type;
};
// ...
};
Run Code Online (Sandbox Code Playgroud)
这允许我们得到一个allocator<U>
给定的allocator<T>
.如果没有这种侵入性实用工具,我们如何才能对容器做同样的事情?在C++ 0x中,它很简单:
template <typename T, typename Container>
struct rebind; // not defined
template <typename T, typename Container, typename... Args>
struct rebind<T, Container<Args...>>
{
// assumes the rest are filled with defaults**
typedef Container<T> type;
};
Run Code Online (Sandbox Code Playgroud)
鉴于std::vector<int>
,我们可以执行rebind<float, std::vector<int>>::type
,例如.与以前的C++ 0x解决方案不同,这个解决方案可以在C++ 03中使用宏和迭代进行仿真.
**注意这个机制可以变得更加强大,比如指定要保留哪些参数,重新绑定哪些参数,在用作参数之前重新绑定哪些参数等等,但这仍然是读者的练习.:)
我有点困惑为什么一些非常聪明(和称职)的人说不.
除非我误读了您的问题,否则您要完成的任务与标准库中的"容器适配器"几乎完全相同.每个都提供了一些底层容器类型的接口,其中将使用的容器类型作为模板参数提供(具有默认值).
例如,std::stack
使用一些其他的容器(如std::deque
,std::list
或std::vector
)持有的对象,std::stack
本身只是提供了当你只是想使用的堆栈操作的简化/受限制的接口.将由其使用的基础容器std::stack
作为模板参数提供.以下是代码在标准中的外观:
namespace std {
template <class T, class Container = deque<T> >
class stack {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef Container container_type;
protected:
Container c;
public:
explicit stack(const Container& = Container());
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
value_type& top() { return c.back(); }
const value_type& top() const { return c.back(); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_back(); }
};
}
Run Code Online (Sandbox Code Playgroud)
当然,也许我只是误解了这个问题 - 如果是这样的话,我会事先向那些我(有点)不同意的人道歉.
是的,不是.
您可以使用模板模板参数,例如,
template <typename Item, template <typename> class Container>
struct TList { /* ... */ };
Run Code Online (Sandbox Code Playgroud)
但是,通常,模板模板参数不是特别有用,因为模板参数的数量和类型必须匹配.因此,上面的内容不匹配,std::vector
因为它实际上有两个模板参数:一个用于值类型,另一个用于分配器.模板模板参数无法利用任何默认模板参数.
为了能够将std::vector
模板用作参数,TList
必须声明为:
template <typename Item, template <typename, typename> class Container>
struct TList { /* ... */ };
Run Code Online (Sandbox Code Playgroud)
但是,使用此模板,您将无法将std::map
模板用作参数,因为它有四个模板参数:键和值类型,分配器类型和比较器类型.
通常,由于这种不灵活性,避免模板模板参数要容易得多.
归档时间: |
|
查看次数: |
1523 次 |
最近记录: |