接受另一个模板参数的模板模板集合
Template template collection accepting another template argument
我正在努力思考模板模板如何工作以实现如下所示的类似功能。
考虑两个 classes(在 Java 中)。第一个 class 通过指定只能在其中存储第二个模板参数的对象来限制 pack
方法返回的集合:
abstract class ContainerPacker<T, Container extends Collection<T>> {
abstract Container pack(T t);
}
这个 class 的实现,比方说,Integer
类型可能如下所示:
class IntegerContainerPacker extends ContainerPacker<Integer, List<Integer>> {
@Override
List<Integer> pack(Integer t) {
List<Integer> list = new ArrayList<>(t);
list.add(t);
return list;
}
}
现在我想使用模板模板在 C++ 中做一些类似的事情。注意 Container
本身是一个模板:
template <typename T, template <typename U> class Container>
class ContainerPacker {
public:
virtual Container<T> pack(T) = 0;
};
不过我在实施时遇到了问题。以下代码无法编译:
class IntegerVectorPacker : public ContainerPacker<int, std::vector> {
public:
std::vector<int> pack(int t) {
std::vector<int> v = std::vector<int>();
v.push_back(t);
return v;
}
};
错误是:
error: type/value mismatch at argument 2 in template parameter list for ‘template class Container> class ContainerPacker’
class IntegerVectorPacker : public ContainerPacker {
和
note: expected a template of type ‘template class Container’, got ‘template class std::vector’
我一直在寻找答案,但甚至不知道要问什么问题。模板模板很难。
试试
template <typename T, template <typename...> class Container>
您的代码中的问题(一个问题?)是 std::vector
是一个模板 class,它接收多个模板参数(两个:第二个具有默认类型);所以不匹配 Container
.
将 Container
定义为接收零个或多个模板应该允许与 std::vector<int>
(实际上是 std::vector<int, std::allocator<int>>
)和其他容器匹配。
-- 编辑 --
我现在看到你用 C++ 标记了这个问题,而不是 C++11(或更新版本)。
typename...
建议仅从 C++11 开始有效,因为可变参数模板以前不可用。
对于 C++98 你可以这样写
template <typename T, template <typename, typename> class Container>
但这只适用于两个参数容器。
-- 编辑 2 --
题外话建议。
如果您可以使用 C++11 或更新版本(因此可变参数模板),将 Container
和 T
的顺序切换为 ContainerPacker
并转换 T
是一个可变参数包;像
template <template <typename...> class Container, typename ... Ts>
class ContainerPacker {
public:
virtual Container<Ts...> pack(Ts...) = 0;
};
它更灵活。
我正在努力思考模板模板如何工作以实现如下所示的类似功能。
考虑两个 classes(在 Java 中)。第一个 class 通过指定只能在其中存储第二个模板参数的对象来限制 pack
方法返回的集合:
abstract class ContainerPacker<T, Container extends Collection<T>> {
abstract Container pack(T t);
}
这个 class 的实现,比方说,Integer
类型可能如下所示:
class IntegerContainerPacker extends ContainerPacker<Integer, List<Integer>> {
@Override
List<Integer> pack(Integer t) {
List<Integer> list = new ArrayList<>(t);
list.add(t);
return list;
}
}
现在我想使用模板模板在 C++ 中做一些类似的事情。注意 Container
本身是一个模板:
template <typename T, template <typename U> class Container>
class ContainerPacker {
public:
virtual Container<T> pack(T) = 0;
};
不过我在实施时遇到了问题。以下代码无法编译:
class IntegerVectorPacker : public ContainerPacker<int, std::vector> {
public:
std::vector<int> pack(int t) {
std::vector<int> v = std::vector<int>();
v.push_back(t);
return v;
}
};
错误是:
error: type/value mismatch at argument 2 in template parameter list for ‘template class Container> class ContainerPacker’ class IntegerVectorPacker : public ContainerPacker {
和
note: expected a template of type ‘template class Container’, got ‘template class std::vector’
我一直在寻找答案,但甚至不知道要问什么问题。模板模板很难。
试试
template <typename T, template <typename...> class Container>
您的代码中的问题(一个问题?)是 std::vector
是一个模板 class,它接收多个模板参数(两个:第二个具有默认类型);所以不匹配 Container
.
将 Container
定义为接收零个或多个模板应该允许与 std::vector<int>
(实际上是 std::vector<int, std::allocator<int>>
)和其他容器匹配。
-- 编辑 --
我现在看到你用 C++ 标记了这个问题,而不是 C++11(或更新版本)。
typename...
建议仅从 C++11 开始有效,因为可变参数模板以前不可用。
对于 C++98 你可以这样写
template <typename T, template <typename, typename> class Container>
但这只适用于两个参数容器。
-- 编辑 2 --
题外话建议。
如果您可以使用 C++11 或更新版本(因此可变参数模板),将 Container
和 T
的顺序切换为 ContainerPacker
并转换 T
是一个可变参数包;像
template <template <typename...> class Container, typename ... Ts>
class ContainerPacker {
public:
virtual Container<Ts...> pack(Ts...) = 0;
};
它更灵活。