gpt4 book ai didi

c++ - C++如何考虑常量性,模板化性和泛型性来解析专用模板?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:30:49 25 4
gpt4 key购买 nike

我有以下代码,可能看起来有些费解,但来自真实代码:

#include <iostream>
using namespace std;

template <class Hrm, class A>
void foo(Hrm& h, A& a)
{
cout << "generic" << endl;
}

template <template <bool> class Hrg>
void foo(Hrg<false>& h, int& a)
{
cout << "specialized int" << endl;
}

template <template <bool> class Hrg>
void foo(Hrg<true>& h, const int& a)
{
cout << "specialized const-int" << endl;
}

template <bool W>
struct what;

template<> struct what<true> { };
template<> struct what<false> { };


int main() {
what<true> wt;
what<false> wf;

int i = 5;
const int& ri = i;

foo(wt, i); // 1) generic
foo(wf, i); // 2) specialized int
foo(wt, ri); // 5) specialized const-int
foo(wf, ri); // 6) generic
return 0;
}

Ideone link

我了解 4:对于带有 Hrg的错误 const int,它没有专门的名称,因此将其称为通用版本。

我的问题是,为什么在其他情况下需要调用给定的函数? 3似乎称为专用const版本,因为 const intA更“直接”匹配。我想知道为什么会更具体地发生。

而且, 12呢?特别是, 1对我来说非常令人惊讶:为什么调用 generic版本而不是专用的const-int?

附加说明:如果我将 foo的两个特化更改为:
template <template <bool> class Hrg>
void _foo(Hrg<false>& h, int& a)
{
cout << "specialized int" << endl;
}

template <template <bool> class Hrg>
void _foo(Hrg<true>& h, const int& a)
{
cout << "specialized const-int" << endl;
}

template <class Hrg>
void foo(Hrg& h, int& a)
{
return _foo(h, a);
}

template <class Hrg>
void foo(Hrg& h, const int& a)
{
return _foo(h, a);
}

然后输出变为:
foo(wt, i);     // a) specialized const-int
foo(wf, i); // b) specialized int
foo(wt, ri); // c) specialized const-int
//foo(wf, ri); // d) compilation error

对我来说,这是一个更加直观的结果。

最佳答案

解决过载的步骤如下:

  • 集合了一组候选函数。这组候选者由非模板功能和功能模板的专业组成。如果模板参数推导在功能模板上失败,则将其从候选集中静默删除。
  • 候选功能的子集被确定为可行。这意味着它具有的参数数量与参数数量兼容,并且每个参数都可以隐式转换为相应的参数类型。 (请注意,即使转换是模棱两可的,该函数仍然可行;但是在这种情况下,仍然可以选择该函数,然后您会收到编译错误)。
  • 比较可行的功能。对于给定的一对可行函数,从某种意义上讲,为了从给定参数初始化函数的参数需要较少的隐式转换,被认为比其他函数“更好”。请注意,给定两个功能,可能没有一个比另一个更好。通常,这些规则足以确定一个可行的功能要优于所有其他功能。该功能将赢得重载解决方案。
  • 如果有两个函数,并且两个函数都不比另一个更好,那么在某些情况下[1]应用平局决胜规则,该规则可能仍然确定一个函数比另一个更好。如果规则3无法确定两个可行功能中的哪一个更好,而只有一个是非模板,则非模板会更好;如果两者都是模板专长,但是其中一个是从比另一个更专业的模板生成的,那么该功能会更好。在决胜局之后,如果有一个最佳可行的功能(比其他所有功能都强),那么该功能将赢得重载解决方案。如果歧义性仍然存在,则重载解析将失败并且该调用将是模棱两可的。

  • 重要的是要记住,步骤4是在步骤3之后执行的; “通用性”或“模板性”是 ,仅是一条平局规则。

    让我们在第一个代码块中查看所有示例。

    (1)第一次和第三次重载成功扣除;不能第二次推导 Hrg。因此,候选人是第一名和第三名(规则1)。两者都是可行的(规则2)。第一个重载会将 i绑定(bind)到 int&,而第三个重载将 i绑定(bind)到 const int&。首选与cv资格较弱的引用文献相结合(规则3)。 (Barry从标准中得到了具体的报价。)第一个(通用)重载获胜。

    (2)不能为第三次重载推导 Hrg,因此它不是候选值(规则1)。第一个和第二个是候选人,并且是可行的(规则2)。第一个和第二个重载都完全匹配,无需进行任何转换,并且按规则3不能区分。第二个重载是因为它更专业(规则4)。

    (5)对于第二个重载, Hrg的推导失败,因此它不是候选者,而第一个和第三个重载是(规则1)。请注意,对于第一个重载, A推导为 const int,产生与第三个重载相同的签名。它们都是可行的(规则2),在规则3的末尾是无法区分的。第三个重载是成功的,因为它更专业(规则4)。

    (6)对于第三个重载, Hrg的推导失败,因此它不是候选者,而第一个和第二个是(规则1)。第二次重载是不可行的(规则2),因为 int&无法绑定(bind)到 ri,即 const。第一个重载,即通用重载,是唯一可行的功能,因此胜出。

    我将重载分辨率留在第二个代码块中,作为读者的练习。

    [1]作为T.C.在评论中指出,这里有一个微妙之处。打破平局规则仅适用于对于给定的一对功能,为每对对应的参数均等地对从参数初始化参数所需的隐式转换序列进行排序的情况。如果第一个函数对一个参数的隐式转换顺序更好,而第二个函数对不同参数的隐式转换顺序更好,则不采用平局决胜规则,并且保持歧义。但是,在问题的示例中不会发生这种情况。

    关于c++ - C++如何考虑常量性,模板化性和泛型性来解析专用模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30064094/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com