【问题标题】:std::pair<K,V> templated function not called template overloading not workingstd::pair<K,V> 模板化函数未调用模板重载不起作用
【发布时间】:2019-12-19 08:39:26
【问题描述】:

模板重载在当前场景中不起作用。

我有一个重载模板程序和一个包含映射、对和向量的复杂数据结构。 没有为 std::pair 调用重载的模板函数。 我无法弄清楚它的原因。它正在调用#1 通用模板函数。

#include <iostream>
#include <vector>
#include <map>
#include <utility>
template <typename T>
bool f(T& x) // #1
{
    std::cout << "body of f\n";
    return f(x);
}

template <typename T>
bool f(std::vector<T>& v) // #2
{
    std::cout << "body of f for vectors\n";
    return true;
}

template <typename Key, typename Value>
bool f(std::pair<Key,Value>& v) // #3
{
    std::cout << "body of f for pairs\n";
    for(auto& e: v) {
      f(e.first);
    }
    for(auto& e: v) {
      f(e.second);
    }
    return true;
}

template <typename Key, typename Value>
bool f(std::map<Key,Value>& v) // #4
{
    std::cout << "body of f for maps\n";
    for(auto& e: v) {
      f(e.first);  // expecting this call goes to #3
    }
    for(auto& e: v) {
      f(e.second);
    }
    return true;
}

int main() {
  std::vector<int> v{1,2};
  std::map<std::pair<int,int>,std::vector<int>> m_map = {
                                            {{10,20}, {5,6}},
                                            {{11,22}, {7,8}}
                                        };
    f(m_map); // this call goes to #4
}

控制台输出是

body of f for maps
body of f
body of f
body of f
body of f
body of f .... Goes on infinitely

请告诉我这段代码有什么问题。

谢谢。

【问题讨论】:

  • “无限继续”部分很容易解释:在调用f(x) 时的template &lt;typename T&gt; bool f(T&amp; x) 函数中,f 唯一已知的重载就是它自己。这意味着你有一个无限递归。
  • 顺便说一句,#3 的正文是错误的,您不能在对上进行迭代...

标签: c++ templates overloading template-specialization std-pair


【解决方案1】:

首先,std::map&lt;std::pair&lt;int,int&gt;,std::vector&lt;int&gt;&gt; 类型的 m_map 具有值类型 std::pair&lt;const std::pair&lt;int,int&gt;, std::vector&lt;int&gt;&gt;。因此,在#4 中,e 的类型为std::pair&lt;const std::pair&lt;int,int&gt;, std::vector&lt;int&gt;&gt;&amp;e.first 的类型为const std::pair&lt;int,int&gt;

f(e.first) 不会调用#3,因为您不能将非 const 左值引用绑定到 const 对象。如果将其参数从std::pair&lt;Key,Value&gt;&amp; v 更改为const std::pair&lt;Key,Value&gt;&amp; v,它将起作用。但是,它最终会出现编译错误,因为您不能使用基于范围的 for 循环对一对进行迭代。改变

for(auto& e: v) {
  f(e.first);
}
for(auto& e: v) {
  f(e.second);
}

f(e.first);
f(e.second);

#3

最后,您错过了ints 的最终重载以停止无限递归。添加如下内容:

bool f(int i) {
  std::cout << "body of f for ints\n";
  return true; 
}

工作live demo

【讨论】:

  • @TechTotie 不客气,欢迎来到 StackOverflow。请注意,我们不会在 cmets 中说“谢谢”之类的话。这些旨在用于有用的主题讨论。支持和接受答案是间接说“谢谢”的最好和足够的方式:)。
【解决方案2】:

map 上的迭代是在 std::pair&lt;const Key, value&gt; 上完成的,所以使用

std::map<std::pair<int,int>,std::vector<int>> m_map;

你会打电话的

f(const std::pair<int,int>&)

仅匹配 #1。

由于您不修改任何元素,我建议将 const 添加到每个输入引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多