没有匹配的构造函数来初始化“string”(又名“basic_string<char>”)

问题描述 投票:0回答:2

这是代码:

#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 --版本:

clang version 3.5.0 (tags/RELEASE_350/final 216961)
Target: x86_64-suse-linux
Thread model: posix

谢谢

c++ string c++11 clang
2个回答
6
投票

我相信这是一个 clang bug。根据[dcl.init.list]中列表初始化的规则:

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

  • 如果
    T
    是类类型,并且初始值设定项列表具有 cv
    U
    类型的单个元素,其中
    U
    T
    或从
    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

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

第一个参数没有从

Foo
const std::__cxx11::basic_string<char> &
的已知转换

但是有,所以我将其归档为 LLVM Bug 23658


0
投票

我也猜是 clang bug。消除此类错误的解决方案之一是使用定义的变量来调用函数。例如,如果我想调用这个函数:

myFunction(int& a, string& b)
,而不是通过按值调用
myFunction(2, "Hello")
来调用它,我会这样做
int a = 2; string b = "Hello"; myFunction(a, b);
,并且boom clang将不再显示这种错误。感谢您提出这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.