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 typecv U
, whereU
isT
or a class derived fromT
, 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 classT
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