首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clang和gcc为同一代码产生的不同逻辑。哪个是对的?

clang和gcc为同一代码产生的不同逻辑。哪个是对的?
EN

Stack Overflow用户
提问于 2019-02-01 09:30:44
回答 1查看 427关注 0票数 12

我发现gcc-8和clang-6的逻辑不一致.

这发生在一个真正的代码库中,当我使用clang开发时,我使用gcc进行部署。

请告知哪个编译器是错误的,以便我可以适当地提交一个错误。

提要

A可以隐式转换为BA可以从A (复制/移动)和std::initializer_list<B>构建。

A初始化A&&

  • clang选择移动构造函数。
  • gcc选择initializer_list构造函数。

现场演示:https://coliru.stacked-crooked.com/a/bc50bd8f040d6476

MCVE

代码语言:javascript
复制
#include <initializer_list>
#include <utility>
#include <iostream>

struct thing;

struct thing_ref
{
    thing_ref(thing&& other) : ref_(other) {}
    thing_ref(thing& other) : ref_(other) {}

    thing& ref_;
};

struct thing
{
    thing() {}

    thing(std::initializer_list<thing_ref> things)
    {
        std::cout << "initializer_list path\n";
    }

    thing(thing&& other)
    {
        std::cout << "move path\n";
    }

    thing(thing const& other)
    {
        std::cout << "copy path\n";
    }
};

struct foo
{
    foo(thing t) : mything { std::move(t) } {}
    thing mything;
};

int main()
{
    thing t;

    auto f = foo { std::move(t) };
}

编译器设置:

没有什么特别的,根据coliru链接:-std=c++17 -O2

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-01 11:07:17

标准草案(T is thing) [dcl.init.list]

列表初始化是从大括号内的列表中初始化对象或引用...。 列表-对象或T类型引用的初始化定义如下:

  • 如果大括号-init-列表包含指定的初始化项-列表不适用。
  • 如果T是一个聚合类且不适用
  • 否则,如果T是字符数组,则不应用
  • 否则,如果T是一个聚合,则不适用
  • 否则,如果初始化程序列表中没有元素,则不应用
  • 否则,如果T是std::initializer_­list<E>的专门化,则不适用
  • 否则,如果T是类类型,则考虑构造函数。列举了适用的构造函数,并通过重载解析选择了最优的构造函数,应用
  • ..。

[over.match.list]

当对非聚合类类型T的对象进行列表初始化以使dcl.init.list指定根据本项中的规则执行重载解析时,重载解析将分两个阶段选择构造函数:

  • 最初,候选函数是类T的初始化器-列表构造函数 (dcl.init.list),参数列表由作为单个参数的初始化程序列表组成。应用
  • 如果没有找到可行的初始化程序列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化程序列表的元素组成。

如果初始化程序列表没有元素,而T具有默认构造函数,则省略第一阶段。不适用

返回到dcl.init.list,了解https://timsong-cpp.github.io/cppwp/n4659/dcl.init#list-2是什么:

如果构造函数的第一个参数是std::initializer_­list<E>类型,或者引用了某些类型E的cv限定的std::initializer_­list<E>,并且没有其他参数,或者所有其他参数都具有默认参数(dcl.fct.default),则构造函数就是初始化-列表构造函数。

还有一个方便的说明,重申了这一结论:

注意:在列表初始化中,初始化-列表构造函数比其他构造函数更受青睐。

我的结论是:

应首先考虑初始化项-列表构造函数候选项,并在其有效时使用。当thing隐式转换为thing_ref时,它应该是有效的。在我看来,GCC是在服从。

如果要初始化具有初始化程序-列表构造函数的类型对象,但不想使用该构造函数,则不要使用列表初始化,即不要使用大括号-init- list。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54476572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档