使用模板参数模板解决模棱两可调用的 C++ 默认行为是啥?

Posted

技术标签:

【中文标题】使用模板参数模板解决模棱两可调用的 C++ 默认行为是啥?【英文标题】:What is c++ default behavior to resolve ambiguous calls with template of template parameter?使用模板参数模板解决模棱两可调用的 C++ 默认行为是什么? 【发布时间】:2016-11-08 18:12:50 【问题描述】:

考虑以下代码:

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
void f(T& a) 
    cout << "a" << endl;

template <typename T>
void f(vector<T>& a) 
    cout << "b" << endl;


int main(int argc, char** argv) 
    vector<vector<int>> v;
    f<vector<vector<int>>>(v);
    f<vector<int>>(v);
    f(v);

在对 f 的前两次调用中,我明确指定了要使用的模板版本,因此我可以控制要调用的函数的版本。

第三个隐式调用应该是模棱两可的,因为我们有两个第一个调用显示的选择。令人惊讶的是,g++ 编译器并没有侮辱我,并且毫无怨言地完成了它的工作。

输出是

a
b
b

这意味着f&lt;vector&lt;int&gt;&gt; 已用于第三次调用。

那么这种情况下的默认行为是什么?我的理论是,它采用在这种情况下有意义的最严格的例子。 这是真的?这是在某处指定的,因为我不能相信随机性。

这里的向量类没有什么特别之处。我实际上是在实现一些图算法,但是由于我可能对图有不同的表示形式,例如作为邻接表向量 >> 或作为弧表向量 > ,以及弧的不同表示取决于它是否是未加权/加权图/流网络,它可能携带不同类型的信息。我正在尝试使用模板编写通用代码,但目前我正面临这种问题。

谢谢

【问题讨论】:

重载解决的逻辑并不总是显而易见的。有很多细节。见more on the subject。 【参考方案1】:

您的第二个 f 据说比您的第一个 f更专业,因此当两者都匹配时,第二个 f 将赢得重载决议。

更专业的确切定义在标准中详细给出,但基本思想是弄清楚对一个的任何调用是否总是可以被另一个匹配(但不是副-反之亦然)。也就是说,如果您有第二个fstd::vector&lt;X&gt;&amp;,您知道它也可以匹配第一个fT&amp;。但是,如果第一个 f 有一个通用的 X&amp;,则不能保证它会匹配第二个 fstd::vector&lt;T&gt;&amp;

【讨论】:

以上是关于使用模板参数模板解决模棱两可调用的 C++ 默认行为是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理模棱两可的模板参数?

实验2:函数重载函数模板简单类的定义和实现

在 C++ 中使用默认参数跳过模板参数真的不可能吗,为啥语法建议不这样?

为啥接受数组的 C++ 模板并不比接受 GCC 5.3 和 Clang 4.0 的指针更专业?

C++类模板常见用途和注意实现

C++ 模板详解(转)