C ++编译错误构造具有rvalue std :: string的对象 [英] C++ compile error constructing object with rvalue std::string
问题描述
我遇到一个编译错误,我甚至不知道如何描述!
代码尝试创建一个
代码:
#include< iostream>
#include< string>
class Foo
{
public:
Foo(double d)
:mD(d)
{
} b
$ b Foo(const std :: string& str)
{
try
{
mD = std :: stod(str);
}
catch(...)
{
throw;
}
}
Foo(const Foo& other)
:mD(other.mD)
{
}
virtual〜Foo(){}
protected:
double mD;
};
class Bar
{
public:
Bar(const Foo& a,const Foo& b)
:mA(a)
,mB(b)
{
}
virtual〜Bar(){}
protected:
Foo mA;
Foo mB;
};
int main(int argc,char * argv [])
{
if(argc <3){return 0; }
Foo a(std :: string(argv [1]));
Foo b(std :: string(argv [2]));
Bar wtf(a,b);
}
编译器错误:
> g ++ -std = c ++ 11 wtf.cpp
wtf.cpp:在函数'int main(int,char * *)':
wtf.cpp:58:17:error:没有匹配函数调用'Bar :: Bar(Foo(&)(std :: string *),Foo(& :: string *))'
Bar wtf(a,b);
^
wtf.cpp:38:9:note:candidate:Bar :: Bar(const Foo& amp; const Foo&)
Bar(const Foo& a,const Foo& b)
^
wtf.cpp:38:9:注意:没有从Foo(std :: string *)的参数1的已知转换{aka Foo(std :: basic_string< char&到'const Foo&'
wtf.cpp:35:7:note:candidate:Bar :: Bar(const Bar&)
class Bar
^
wtf.cpp: 35:7:note:candidate expects 1 argument,2 provided
>
你不会相信/ a解决方法是, 不要)。如果我调用substr(0)在我的右值std :: string,编译器被平安。但我不明白为什么这会有所作为。毕竟...
std :: string(argv [1])substr(0)
...本身仍然是一个右值。我不明白为什么它不同于编译器的观点。
对main(...)的以下更改允许编译成功:
int main(int argc,char * argv [])
{
if(argc <3){return 0; }
Foo a(std :: string(argv [1])。substr(0));
Foo b(std :: string(argv [2])。substr(0));
Bar wtf(a,b);
}
几个额外的数据点:
- 编译没有C ++ 11没有什么区别(我只包括它访问std :: stod(...),这是除了点)。
- g ++(GCC)5.4.0。
- 编译环境是cygwin。
- 使用std :: string(而不是std :: string&) - 它不会影响编译错误。
强>死亡,以了解这是什么问题。
感谢您的帮助。
这是最烦琐的解析的较不常见的示例。声明
Foo a(std :: string(argv [1]));
不会调用 Foo
的构造函数字符串参数相反,它声明 a
是一个函数取数组1 std :: string
(调整为指针到 std :: string
)并返回 Foo
。这就是为什么错误消息提到一个 Foo(&)(std :: string *)
type:这是编译器认为 code>和
b
。 (消息中的(&)
只是意味着它是一个左值。)
添加 .substr(0)
消除声明,使其不能作为函数声明解析。
大括号初始化是一种更加优雅的方式解决问题:
Foo a {std :: string(argv [1])};
I'm faced with a compile error that I don't even know how to describe! It completely baffles me.
The situation:
Code tries to create an object on the stack with an rvalue std::string that is initialized with a char*.
The code:
#include <iostream>
#include <string>
class Foo
{
public:
Foo(double d)
: mD(d)
{
}
Foo(const std::string& str)
{
try
{
mD = std::stod(str);
}
catch (...)
{
throw;
}
}
Foo(const Foo& other)
: mD(other.mD)
{
}
virtual ~Foo() {}
protected:
double mD;
};
class Bar
{
public:
Bar(const Foo& a, const Foo& b)
: mA(a)
, mB(b)
{
}
virtual ~Bar() {}
protected:
Foo mA;
Foo mB;
};
int main(int argc, char* argv[])
{
if (argc < 3) { return 0; }
Foo a(std::string(argv[1]));
Foo b(std::string(argv[2]));
Bar wtf(a, b);
}
The compiler error:
>g++ -std=c++11 wtf.cpp
wtf.cpp: In function ‘int main(int, char**)’:
wtf.cpp:58:17: error: no matching function for call to ‘Bar::Bar(Foo (&)(std::string*), Foo (&)(std::string*))’
Bar wtf(a, b);
^
wtf.cpp:38:9: note: candidate: Bar::Bar(const Foo&, const Foo&)
Bar(const Foo& a, const Foo& b)
^
wtf.cpp:38:9: note: no known conversion for argument 1 from ‘Foo(std::string*) {aka Foo(std::basic_string<char>*)}’ to ‘const Foo&’
wtf.cpp:35:7: note: candidate: Bar::Bar(const Bar&)
class Bar
^
wtf.cpp:35:7: note: candidate expects 1 argument, 2 provided
>
You won't believe what the/a workaround is, either (or at least I don't). If I call substr(0) on my rvalue std::string, the compiler is pacified. But I don't see why this would make a difference. After all...
std::string(argv[1]).substr(0)
...is itself still an rvalue. I don't see why it's different from the compiler's point of view.
I.e. the following change to main(...) allows compilation success:
int main(int argc, char* argv[])
{
if (argc < 3) { return 0; }
Foo a(std::string(argv[1]).substr(0));
Foo b(std::string(argv[2]).substr(0));
Bar wtf(a, b);
}
Couple of additional data points:
- Compiling without C++11 makes no difference (I only include it to get access to std::stod(...), which is besides the point).
- g++ (GCC) 5.4.0.
- Compilation environment is cygwin.
- I have tried modifying Bar's constructor to take std::string (instead of std::string&) - it does not affect the compile error.
I'm dying to know what this problem is. This feels so out of left field.
Thanks for any help.
This is a less common example of the most vexing parse. The declaration
Foo a(std::string(argv[1]));
is not calling the constructor of Foo
with a string argument; instead, it is declaring a
to be a function taking an array of 1 std::string
(adjusted to a pointer to std::string
) and returning Foo
. That's why the error message is mentioning a Foo (&)(std::string*)
type: that's the type the compiler thinks a
and b
are. (The (&)
in the message just means that it's an lvalue.)
Adding .substr(0)
disambiguates the declaration so that it cannot be parsed as a function declaration.
Brace initialization is a more elegant way to solve the problem:
Foo a{std::string(argv[1])};
这篇关于C ++编译错误构造具有rvalue std :: string的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!