以下是代码:
#include <iostream>
#include <string>
using namespace std;
class Foo {
public:
operator string() const { return n; }
string n {"foo"};
};
int main (int argc, char** argv) {
string s {Foo{}};
cout << s << endl;
return 0;
}
这段代码使用gcc 4.8.3编译,但不能使用clang 3.5编译,有人能告诉我它有什么问题吗?
我收到了这样的错误:
main.cpp:45:12: error: no matching constructor for initialization of 'string' (aka 'basic_string<char>')
string s {Foo{}};
^ ~~~~~~~
clang --version:
clang version 3.5.0 (tags/RELEASE_350/final 216961)
Target: x86_64-suse-linux
Thread model: posix
由于
答案 0 :(得分:6)
我相信这是一个铿锵的错误。根据[dcl.init.list]中列表初始化的规则:
类型
T
的对象或引用的列表初始化定义如下:
- 如果
派生的类T
是类类型且初始值设定项列表包含 cvU
类型的单个元素,则其中U
为T
或从T
,[...]- 否则,如果
T
是字符数组且[...]- 否则,如果
T
是聚合,[...]- 否则,如果初始化列表没有元素[...]
- 否则,如果
T
是std::initializer_list<E>
的特化,[...]- 否则,如果
T
是类类型,则考虑构造函数。列举了适用的构造函数 通过重载决策选择最好的一个(13.3,13.3.1.7)。如果缩小转换(见 如果需要转换任何参数,程序就是格式错误。- [...]
T
是一种类型,因此我们考虑basic_string
constructors。该列表中的#7(复制构造函数)是一个适用的,可行的构造函数,因此应该选择它。那时,这些表达式应该是等价的:
struct Foo {
operator std::string() const { return "hello"; }
};
std::string s{Foo{}}; // error
std::string s(Foo{}); // OK
std::string s = Foo{}; // OK
出于某种原因,在列表初始化的情况下,clang抱怨:
第一个参数
没有从Foo
到const std::__cxx11::basic_string<char> &
的已知转换
但是,我将其归档为LLVM Bug 23658。