代码之家  ›  专栏  ›  技术社区  ›  MK.

嵌套模板函数获取两个内部类型相同的容器

  •  2
  • MK.  · 技术社区  · 6 年前

    我正在尝试编写一个函数,它大致类似于一个接受两个容器实例(现在假设它们是相同的)的函数,包含相同的类型并合并它们。这里是向量的函数:

    template<typename T>
    void test(std::vector<T> v1, std::vector<T> v2) {
      std::cout << "called nested for c\n";
    }
    

    而且有效。

    现在,我想有一个将工作集或向量。我试试这个:

    template<typename T, template <typename> typename C >
    void test(C<T> v1, C<T> v2) {
      std::cout << "called nested for c<t>\n";
    }
    

    然后得到

    cc:33:6:注意:模板参数演绎/替换 失败:nestedt.cc:43:12:错误:模板参数数目错误 (3,应为1)试验; ^nestedt.C C:32:51:注意:为模板类C提供模板类型名C> ^

    我试过了

    template< template <typename T> typename C >
    void test(C<T> v1, C<T> v2) {}
    
    std::set<int> s = {1,2};
    test(s, s);
    

    但这不管用:

    cc:32:6:注意:模板参数演绎/替换 失败:nestedt.cc:42:12:注意:无法转换s(类型 std::set)设置为int类型测试; ^

    所以我试着

    template<typename C, typename T >
    void test(C<T> v1, C<T> v2) {}
    

    然后得到

    nestedt.cc:32:6:注意:候选:模板无效 试验(C,C)无效试验(C v1,C v2){ ^nestedt.cc:32:6:注意:模板参数推断/替换失败:nestedt.cc:42:12:注意:无法 推导出模板参数T检验(s,s); ^

    我觉得我甚至不理解模板在C++中是如何工作的,它是如此的悲伤。 实际上,我希望容器是不同的。理想情况下,能够以某种方式指定一组有限的允许容器。它们不是真正的std::容器。

    注意,最终的目标是能够携带两个不同的容器,所以 test(vector<int>, set<int>) . 而且改变容器是不可能的。

    3 回复  |  直到 6 年前
        1
  •  2
  •   Oktalist    6 年前

    你的第一次尝试几乎是对的。因为标准容器 vector 接受多个模板参数。例如,这是 std::vector :

    template<
        class T,
        class Allocator = std::allocator<T>
    > class vector;
    

    您通常从不使用第二个参数,它有一个默认值,但它仍然存在,所以您的模板参数 template <typename> typename C 无法匹配。相反,您可以这样做:

    template<template <typename...> typename C, typename... Ts>
    void test(C<Ts...> v1, C<Ts...> v2) {}
    
        2
  •  2
  •   NathanOliver    6 年前

    我相信你要找的是

    template<template <typename...> typename Cont1, 
             template <typename...> typename Cont2,
             typename... T>
    void test(Cont1<T...> a, Cont2<T...> b) { }
    

    在上面 template <typename...> typename Cont1 声明一个模板模板类型和 template <typename...> typename Cont2 声明另一个容器,以便可以有两种不同的容器类型。两者都有 T... 所以每个模板容器都需要有一个匹配的模板参数列表。这意味着

    test(std::map<int, int>{}, std::map<int, int>{});
    test(std::set<int>{}, std::set<int>{});
    test(std::vector<int>{}, std::set<int>{});
    

    所有工作,但

    test(std::map<int, int>{}, std::vector<int>{});
    test(std::map<int, int>{}, std::set<int>{});
    

    不会。

        3
  •  2
  •   jweyrich    6 年前

    至少需要2个模板参数:

    1. 容器类型
    2. 包含类型

    因为你用的是STL容器 将包含的类型与容器分开传递 ,编译器 无法推断 其他参数(如分配器 std::allocator<T> ,比较 std::less<T> ). 但是可以使用可变模板转发所有嵌套的模板参数。例子:

    template <template <typename...> class C, typename... T>
    struct wrapper {
        typedef C<T...> type;
    };
    wrapper<std::vector, int>::type foo;
    wrapper<std::set   , int>::type bar;
    

    你可以 see it in ideone .