当前位置: 首页 > 知识库问答 >
问题:

gcc上的构造函数重载不明确,但clang上的构造函数重载不明确

段干茂实
2023-03-14

假设我们有以下简单的代码:

#include <iostream>
#include <type_traits>

struct S {
    template <typename T> explicit S(T) noexcept requires std::is_signed<T>::value {
        std::cout << "T\n";
    }
    template<typename T> explicit S(const T&) noexcept {
        std::cout << "const T&\n";
    }
};

int main() {
    S s(4);
}

这段代码使用clang编译并打印“T”,但使用gcc我们有以下错误:

error: call of overloaded 'S(int)' is ambiguous

我的问题是哪个编译器有bug,gcc还是叮当声?

共有1个答案

韶景曜
2023-03-14

GCC是正确的。这是模棱两可的。

首先,我们要看隐式转换序列。在这两种情况下,都涉及身份转换序列:intint,以及intconst int

其次,我们看一下关于标准转换序列的平局规则,[over.ics.ref]/3.2。在这种情况下,这些连接断路器都不适用。这意味着两个隐式转换序列都不比另一个好。

接下来我们要去全球平局决胜局。即使一个重载的所有隐式转换序列既不比另一个重载的相应隐式转换序列好,也不比另一个重载的相应隐式转换序列差,也可以认为一个重载比另一个重载好。[over.match.best.general]/2中定义了全局平局断路器。根据第五个要点(其他任何一个都不可能适用于这种情况),如果两个重载都是模板专用化的,但一个模板比另一个更专用,那么其中一个重载可能会比另一个重载更好。

为了确定情况是否如此,我们参考了[temp.func.order],它指的是[temp.deduct.partial]。我们处于函数调用的上下文中,因此根据(3.1),“使用的类型是函数调用具有参数的那些函数参数类型。”然后,第5段删除了引用,第7段删除了顶级cv限定符。这样做的结果是演绎在两个方向上都成功。(也就是说,即使不是每个T都是const U

回到[temp.func.order],由于推导在两个方向上都成功,第2段中提到的最后一个决胜局是一个模板是否比另一个模板更受约束。为此,我们向下滚动到第6段。适用的要点是(6.2.2),根据它:

否则,如果模板参数列表中对应的模板参数不相等([temp.over.link]),或者如果两个模板之间位置对应的函数参数不是同一类型,则两个模板都比另一个模板更专业。

请注意,在这种情况下,引用和cv限定符的剥离不适用,因为这只是作为演绎的一部分完成的,我们不再进行演绎,所以位置对应的函数参数类型是Tconst T

 类似资料:
  • null 我不太确定如何处理我的代码,以下是我得到的: 我只是不知道我应该打什么。我相信我已经完成了第一个重载构造函数,但我对此还是新手。 那么,我应该做些什么来使重载构造函数工作呢? 我对Java和面向对象编程非常陌生。

  • 本文向大家介绍C++中构造函数重载,包括了C++中构造函数重载的使用技巧和注意事项,需要的朋友参考一下   当类中没有定义构造函数时,C++编译器自动提供无参构造函数和拷贝构造函数   当类中定义了任意的拷贝构造函数,C++不提供无参构造函数。 系统自动提供的构造函数   无参构造函数      函数体为空   拷贝构造函数      简单的进行成员变量的值复制      Test t1;    

  • 问题内容: 我在Java中使用多个构造函数时遇到麻烦。 我想做的是这样的: 但是我不能,因为第二个构造函数不能调用另一个构造函数,除非它是第一行。 这种情况的常见解决方案是什么?我无法“在线”计算arg2和arg3。我以为也许可以创建一个构造助手方法来完成实际的构造,但是我不确定这是否“漂亮”…… 编辑 :由于我的某些字段是最终的,因此使用辅助方法也是有问题的,我无法使用辅助方法进行设置。 问题答

  • 我试图移植一些为GCC(8.2)编写的代码以供Clang编译: GCC 8.2(和12.1)很好地编译了代码。然而,Clang 11.0.0(和14.0.0)抱怨说,从fe到feh的调用在无效feh之间不明确(Fn https://godbolt.org/z/5E9M6a5c6 哪个编译器是正确的? 如何编写这段代码以便两个编译器都接受它? 这两个和折叠表达式都可以在C 17中使用,但这是许多项目

  • 本文向大家介绍解析C++中构造函数的默认参数和构造函数的重载,包括了解析C++中构造函数的默认参数和构造函数的重载的使用技巧和注意事项,需要的朋友参考一下 C++构造函数的默认参数 和普通函数一样,构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。 【例】 程序运行结果为: 程序中对构造函数的定义(第12-16行)也可以改写成参数初始化