我想构建一个Stack
类,以便用户可以选择要用于实现Stack
的容器。例如,List/Vector
。
部分代码:
stack.h
#ifndef STACK_H_
#define STACK_H_
template <typename T, template<typename T> class ContainerType>
class Stack{
ContainerType<T> container;
public:
Stack() : container(ContainerType<T>()){}
};
#endif /* STACK_H_ */
TEST.CPP
#include "stack.h"
#include <vector>
int main(){
Stack<int, std::vector<int> > stack;
return 0;
}
好吧,它没有编译。我在网上得到了下一个错误:
Stack<int, std::vector<int> > stack;
错误:
expected a class template, got `std::vector<int, std::allocator<int> >' test.cpp
invalid type in declaration before ';' token test.cpp
type/value mismatch at argument 2 in template parameter
list for `template<class T, template<class T> class ContainerType>
class Stack' test.cpp
答案 0 :(得分:22)
首先,它是std::vector
,而不是其他任何内容,因为vector
位于std
命名空间中,并且您要求模板模板参数,虽然std::vector<int>
不再是模板。接下来,std::vector
实际上需要两个模板参数,一个用于类型,另一个用于分配器:
template <
typename T,
template<typename, typename> class ContainerType,
typename Alloc = std::allocator<T>
>
class Stack{
ContainerType<T, Alloc> container;
// ...
};
// usage:
Stack<int, std::vector> s;
现在,这只启用带有两个模板参数的容器作为基础类型,因此您最好使用标准做的事情:将其作为普通类型:
template <typename T, typename ContainerType>
class Stack{
ContainerType container;
// ...
};
// usage:
Stack<int, std::vector<int> > s;
要确保底层类型具有相同的T
,您可以执行虚假的“静态断言”,或者如果您启用了C ++ 0x编译器,则可以执行实际的静态断言:
#include <tr1/type_traits> // C++03 us std::tr1::is_same
//#include <type_traits> // C++0x, use std::is_same
template <typename T, typename ContainerType>
class Stack{
typedef typename ContainerType::value_type underlying_value_type;
typedef char ERROR_different_value_type[
std::tr1::is_same<T, underlying_value_type>::value ? 1 : -1
]
ContainerType container;
// ...
};
这是有效的,因为如果T
与使用的容器的T
不同,它将是typedef char ERROR_different_vale_type[-1]
,并且可能不存在负大小的数组,这会导致编译器错误。 :)现在,使用C ++ 0x,您只需static_assert
:
#include <tr1/type_traits> // C++03
//#include <type_traits> // C++0x
template <typename T, typename ContainerType>
class Stack{
typedef typename ContainerType::value_type underlying_value_type;
static_assert(std::tr1::is_same<T, underlying_value_type>::value,
"Error: The type of the stack must be the same as the type of the container");
ContainerType container;
// ...
};
为方便起见,您现在可以为常见情况指定默认模板参数:
template <typename T, typename ContainerType = std::vector<T>>
class Stack{
ContainerType container;
// ...
};
// usage:
Stack<int> s;
此时你可以使用std::stack
来完成这一点(尽管它使用std::deque
作为基础类型)。 :)
答案 1 :(得分:2)
由于vector
属于std
命名空间,您必须对其进行限定。但除此之外,因为ContainerType
是模板模板参数,您需要传递模板而不是最终类型:
Stack<int, std::vector > stack;
答案 2 :(得分:2)
最简单的方法是不使用模板模板参数,因为容器的arity存在问题。
相反,只需传递完整的容器类型即可。然后提取value_type
(标准STL内部typedef)以获取值。
template <typename Container>
class Stack
{
public:
typedef typename Container::value_type value_type;
private:
Container _container;
}; // class Stack<Container>
然后,您可以简单地将其用作Stack< std::vector<int> >
,并且它将包含int
s。
答案 3 :(得分:1)
这一行:
Stack<int, vector<int> > stack;
应该是:
Stack<int, std::vector<int> > stack;
或者您可以在test.cpp
前加上
using namespace std;