【问题标题】:Variadic Template, no matching function call可变参数模板,没有匹配的函数调用
【发布时间】:2012-07-09 23:39:49
【问题描述】:

我正在编写zip 的实现,但我遇到了一些问题。这是一个最小的测试用例:

#include <iostream>
#include <deque>
#include <tuple>
#include <string>
#include <limits>

template <template <typename...> class Container, typename... Types>
Container<std::tuple<Types...>> zip(Container<Types> const&... args) {
  unsigned len = commonLength(args...);
  Container<std::tuple<Types...>> res;
  std::tuple<Types...> item;

  for (unsigned i=0; i<len; i++) {
    item = getTupleFrom(i, args...);
    res.push_back(item);
  }

  return res;
}

template <class ContainerA, class... Containers>
unsigned commonLength(ContainerA first, Containers... rest, unsigned len=std::numeric_limits<unsigned>::max()) {
  unsigned firstLen = first.size();
  if (len > firstLen) {
    len = firstLen;
  }
  return commonLength(rest..., len);
}

template <class ContainerA>
unsigned commonLength(ContainerA first, unsigned len=std::numeric_limits<unsigned>::max()) {
  unsigned firstLen = first.size();
  if (len > firstLen) {
    len = firstLen;
  }
  return len;
}

template <template <typename...> class Container, typename TypeA, typename... Types>
std::tuple<TypeA, Types...> getTupleFrom(unsigned index, Container<TypeA> const& first, Container<Types> const&... rest) {
  return std::tuple_cat(std::tuple<TypeA>(first[index]), getTupleFrom(index, rest...));
}

template <template <typename...> class Container, typename TypeA>
std::tuple<TypeA> getTupleFrom(unsigned index, Container<TypeA> const& first) {
  return std::tuple<TypeA>(first[index]);
}

int main() {

  std::deque<int> test1 = {1, 2, 3, 4};
  std::deque<std::string> test2 = {"hihi", "jump", "queue"};
  std::deque<float> test3 = {0.2, 8.3, 7, 123, 2.3};
  for (auto i : zip(test1, test2, test3)) {
    std::cout << std::get<0>(i) << std::get<1>(i) << std::get<2>(i) << std::endl;
  }
  //expected output:
  //1hihi0.2
  //2jump8.3
  //3queue7
  return 0;
}

编译时出现以下错误:

error: no matching function for call to ‘commonLength(const Star::List<int>&, const Star::List<std::basic_string<char> >&, const Star::List<float>&)’
note: candidates are:
note: template<class ContainerA, class ... Containers> unsigned int Star::commonLength(ContainerA, Containers ..., unsigned int)
note: template<class ContainerA> unsigned int Star::commonLength(ContainerA, unsigned int)

我假设我指定我的模板参数错误或类似的东西。我还尝试重新构建并完全消除该功能,但随后我遇到了与 getTupleFrom 相同的错误。

谁能解释一下我为什么这么笨?因为我只是不知道我做错了什么。 :(

【问题讨论】:

    标签: c++ templates c++11 variadic-templates


    【解决方案1】:

    嗯,这行得通:

    #include <iostream>
    #include <deque>
    #include <tuple>
    #include <string>
    #include <type_traits>
    #include <algorithm>
    #include <limits>
    
    template <class ContainerA>
    unsigned commonLength(unsigned len, const ContainerA &first) {
      unsigned firstLen = first.size();
      if (len > firstLen) {
        len = firstLen;
      }
      return len;
    }
    
    
    template <class ContainerA, class... Containers>
    unsigned commonLength(unsigned len, const ContainerA &first, const Containers&... rest) {
      unsigned firstLen = first.size();
      if (len > firstLen) {
        len = firstLen;
      }
      return commonLength(len, rest...);
    }
    
    template <template <typename...> class Container, typename TypeA>
    std::tuple<TypeA> getTupleFrom(unsigned index, Container<TypeA> const& first) {
      return std::tuple<TypeA>(first[index]);
    }
    
    template <template <typename...> class Container, typename TypeA, typename... Types>
    std::tuple<TypeA, Types...> getTupleFrom(unsigned index, Container<TypeA> const& first, Container<Types> const&... rest) {
      return std::tuple_cat(std::tuple<TypeA>(first[index]), getTupleFrom(index, rest...));
    }
    
    template <template <typename...> class Container, typename... Types>
    Container<std::tuple<Types...>> zip(Container<Types> const&... args) {
      unsigned len = commonLength(std::numeric_limits<unsigned>::max(), args...);
      Container<std::tuple<Types...>> res;
      std::tuple<Types...> item;
    
      for (unsigned i=0; i<len; i++) {
        item = getTupleFrom(i, args...);
        res.push_back(item);
      }
    
      return res;
    }
    
    int main() {
    
      std::deque<int> test1 = {1, 2, 3, 4};
      std::deque<std::string> test2 = {"hihi", "jump", "queue"};
      std::deque<float> test3 = {0.2, 8.3, 7, 123, 2.3};
      for (auto i : zip(test1, test2, test3)) {
        std::cout << std::get<0>(i) << std::get<1>(i) << std::get<2>(i) << std::endl;
      }
      //expected output:
      //1hihi0.2
      //2jump8.3
      //3queue7
    }
    

    它的输出完全符合您的预期。问题是:

    • 您没有在commonLength 中使用const&amp; 容器,而zip 的参数在其中引用了const。
    • commonLength中的无符号参数推不出来,所以我把它移到了开头
    • 您以错误的顺序声明/定义函数(A 需要 B,但 A 是在 B 之前定义的),所以我重新排序了。

    显然 clang 3.1 无法推断出 zip 中的模板参数,但 g++ 4.6 可以很好地推导出它们。

    【讨论】:

    • 哈哈,订单声明错误。非常感谢你找到那个。我知道这很愚蠢。
    【解决方案2】:

    一步一步挑选。

    您缺少标题:

    #include <limits>
    

    您有未声明的标识符:

    template <template <typename...> class Container, typename TypeA, typename... Types>
    std::tuple<TypeA, Types...> getTupleFrom(unsigned index, Container<TypeA> const& first, Container<Types> const&... rest) {
      return std::tuple_cat(std::tuple<TypeA>(first[index]), getTupleFrom(index, rest...), end);
    }
    

    end 在哪里声明?

    你前后矛盾:

    Container<std::tuple<Types...>> zip(Container<Types> const&... args) {
      unsigned len = commonLength(args...);
      Container<std::tuple<Types...>> res;
    

    Container&lt;std::tuple&lt;Types...&gt;&gt; 还是Container&lt;Types&gt;?或者这正是你的意思?您的代码有点复杂,仅供快速查看。

    那么,对于Container&lt;TypeA&gt; 的非零计数,您只有getTupleFrom 的版本,

    template <template <typename...> class Container, typename TypeA, typename... Types>
    std::tuple<TypeA, Types...> getTupleFrom(unsigned index, Container<TypeA> const& first, Container<Types> const&... rest) {
      return std::tuple_cat(std::tuple<TypeA>(first[index]), getTupleFrom(index, rest...), end);
    }
    
    template <template <typename...> class Container, typename TypeA>
    std::tuple<TypeA> getTupleFrom(unsigned index, Container<TypeA> const& first) {
      return std::tuple<TypeA>(first[index]);
    }
    

    这就是为什么会有错误

    error: no matching function for call to ‘getTupleFrom(unsigned int&)’
    

    这表明您以某种方式到达了参数列表为空的点(无符号整数参数除外)。我想你需要防止这种情况发生。

    【讨论】:

    • 我将编辑我的帖子。我从一段准功能代码中破解了这个,所以我错过了一个标题,end 是上述尝试删除导致错误的函数的遗物。即使删除它也不能解决问题,但感谢您发现它。
    • + 一个警告“控件到达非空函数的末尾。”
    • 您询问Container&lt;std::tuple&lt;Types...&gt;&gt;Container&lt;Types&gt; 的最新编辑这正是我的意思,这段代码是zip 函数,很像函数的python 版本。它旨在获取多个列表并返回一个元组列表。
    • @jrok:但是我没有看到任何没有 return 语句的非 void 函数。
    • @phresnel,他指的是我最近编辑的main 以抑制警告。
    猜你喜欢
    • 2018-07-02
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    相关资源
    最近更新 更多