接受另一个模板参数的模板模板集合

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 或更新版本(因此可变参数模板),将 ContainerT 的顺序切换为 ContainerPacker 并转换 T 是一个可变参数包;像

template <template <typename...> class Container, typename ... Ts>
class ContainerPacker {
  public:
    virtual Container<Ts...> pack(Ts...) = 0;
};

它更灵活。