其他分享
首页 > 其他分享> > c-lang跳过初始化列表构造的处理

c-lang跳过初始化列表构造的处理

作者:互联网

如果您看下面的代码,我认为main()中的两行都应为InitSomething调用initializer_list构造函数. gcc按照我的预期输出22,但是clang仅输出一个2.clang是否错误?

我正在使用-std = c 14.

#include <iostream>

struct InitSomething {
    explicit InitSomething(int) { std::cout << '1'; }
    InitSomething(std::initializer_list<int> ) { std::cout << '2'; }
    operator int() { return 1; }
};

int main() {
    InitSomething init_something{1};
    InitSomething init_something_else{init_something};
}

clang –version(我在Mac上)的输出是

Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

我提到的另一个平台上g –version的输出是

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

解决方法:

DR1467的标题涉及聚合,但the wording it added to [dcl.init.list]/3作为第一个项目符号不限于聚合:

If T is a class type and the initializer list has a single element
of type cv U, where U is T or a class derived from T, the
object is initialized from that element (by copy-initialization for
copy-list-initialization, or by direct-initialization for
direct-list-initialization).

但是,DR2137从此措辞中退了一步(用“聚合类”替换“类类型”),因此this bullet不再适用于像InitSomething这样的非聚合类.

相反,适用[dcl.init.list] /3.6,就像在DR1467之前一样:

Otherwise, if T is a class type, constructors are considered.
The applicable constructors are enumerated and the best one
is chosen through overload resolution ([over.match],
[over.match.list]).

并且[over.match.list]清楚地表明,如果有可能的话,最好使用initializer-list构造函数:

When objects of non-aggregate class type T are list-initialized such
that [dcl.init.list] specifies that overload resolution is performed
according to the rules in this section, overload resolution selects
the constructor in two phases:

  • Initially, the candidate functions are the initializer-list constructors ([dcl.init.list]) of the class T and the argument list
    consists of the initializer list as a single argument.
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all
    the constructors of the class T and the argument list consists of
    the elements of the initializer list.

所有有关排名隐式转换序列的讨论都是无关紧要的,因为非初始化列表构造器甚至都不是候选者.

Clang在DR1467之后和DR2137之前实施措辞.

标签:c,language-lawyer,c14,clang,gcc
来源: https://codeday.me/bug/20191012/1899887.html