没有用于初始化'string'的匹配构造函数(又名'basic_string <char>')

Art*_*zuk 2 c++ string clang c++11

这是代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

这段代码使用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{}};
           ^ ~~~~~~~
Run Code Online (Sandbox Code Playgroud)

clang --version:

clang version 3.5.0 (tags/RELEASE_350/final 216961)
Target: x86_64-suse-linux
Thread model: posix
Run Code Online (Sandbox Code Playgroud)

谢谢

Bar*_*rry 6

我相信这是一个铿锵的错误.根据[dcl.init.list]中列表初始化的规则:

对象或类型引用的列表初始化T定义如下:

  • 如果T是一个类类型和初始化列表具有类型的单个元件CV U,其中UT或从派生的类T,[...]
  • 否则,如果T是一个字符数组和[...]
  • 否则,如果T是聚合,[...]
  • 否则,如果初始化列表没有元素[...]
  • 否则,如果T是专业化std::initializer_list<E>,[...]
  • 否则,如果T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数.如果转换任何参数需要缩小转换(见下文),则程序格式错误.
  • [...]

T是一个类类型,所以我们考虑basic_string构造函数.该列表中的#7(复制构造函数)是一个适用的,可行的构造函数,因此应该选择它.那时,这些表达式应该是等价的:

struct Foo {
    operator std::string() const { return "hello"; }
};

std::string s{Foo{}};  // error
std::string s(Foo{});  // OK
std::string s = Foo{}; // OK
Run Code Online (Sandbox Code Playgroud)

但是出于某种原因,在列表初始化的情况下,clang抱怨:

没有任何已知的从转换Fooconst std::__cxx11::basic_string<char> &为第一参数

虽然如此,所以我将其作为LLVM Bug 23658提交.

  • 我注意到使用ToT成功编译,并将#23658作为#23657的副本关闭. (2认同)