【发布时间】:2016-12-23 16:09:44
【问题描述】:
我遇到了一个我什至不知道如何描述的编译错误!这完全让我感到困惑。
情况:
代码尝试在堆栈上创建一个带有右值 std::string 的对象,该右值用 char* 初始化。
代码:
#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);
}
编译器错误:
>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
>
您也不会相信/a 解决方法是什么(或者至少我不相信)。如果我在我的右值 std::string 上调用 substr(0),编译器就会被安抚。但我不明白为什么这会有所作为。毕竟……
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。
- 我已尝试修改 Bar 的构造函数以采用 std::string(而不是 std::string&) - 它不会影响编译错误。
我渴望知道这个问题是什么。这感觉太离谱了。
感谢您的帮助。
【问题讨论】:
-
在这种情况下将
std::string&用于Foo的构造函数显然是错误的——它会引用一个临时对象,这充其量是有问题的(尽管我不记得了如果它是非法的或只是未定义)。 -
@SebastianLenartowicz 仅供参考,这是合法的,因为我使用的是 const ref。不同于非常量参考。查看答案 RE:最令人烦恼的解析;太迷人了!
-
与您的问题无关,但
stod调用的 try-catch,如果您所做的只是重新抛出异常,则无需 try-catch。 -
@StoneThrow 对,错过了
const。是的,答案很有趣。我不知道这是一件事! -
@JoachimPileborg 确实如此。取点;谢谢。
标签: c++ constructor std stdstring most-vexing-parse