我遇到了编译错误,我甚至不知道如何描述!这完全让我感到困惑。
情况:
代码尝试使用使用char *初始化的rvalue std :: string在堆栈上创建一个对象。
代码:
>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
>
编译错误:
std::string(argv[1]).substr(0)
你不会相信/ /是一种解决方法(或者至少我不)。如果我在我的rvalue std :: string上调用substr(0),则编译器会被平息。但我不明白为什么这会有所作为。毕竟......
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);
}
......本身仍然是一个左翼。我不明白为什么它与编译器的观点不同。
即。对main(...)的以下更改允许编译成功:
>>> a
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
>>> a < 15
array([[ True, True, True, True, True],
[ True, True, True, True, True],
[ True, True, True, True, False],
[False, False, False, False, False],
[False, False, False, False, False]], dtype=bool)
>>> np.where(a < 15)
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]),
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3]))
其他几个数据点:
我死亡知道这个问题是什么。这感觉离开了场地。
感谢您的帮助。
答案 0 :(得分:28)
这是most vexing parse的一个不太常见的例子。声明
Foo a(std::string(argv[1]));
没有使用字符串参数调用Foo
的构造函数;相反,它声明a
是一个函数,其数组为1 std::string
(调整为指向std::string
的指针)并返回Foo
。这就是错误消息提到Foo (&)(std::string*)
类型的原因:编译器认为a
和b
的类型。 (消息中的(&)
只表示它是左值。)
添加.substr(0)
消除了声明的歧义,因此无法将其解析为函数声明。
支持初始化是解决问题的更优雅的方法:
Foo a{std::string(argv[1])};
答案 1 :(得分:10)
如果仔细查看错误消息,您会发现正在尝试使用两个函数构建wtf
对象a
。这里发生了什么令人烦恼的事情,令人烦恼,它被正式命名为the most vexing parse。
发生的事情是您将b
和std::string
声明为功能。将指针Foo
作为参数并返回Foo
对象的函数。
如果你有一个支持C ++ 11的编译器,你可以在构造Foo a{std::string(argv[1])};
Foo b{std::string(argv[2])};
对象时使用大括号而不是括号:
Foo a = Foo(std::string(argv[1]));
Foo b = Foo(std::string(argv[2]));
如果你有一个较旧的编译器,你可以使用复制初始化:
std::string
如果您不显式创建构造函数参数的Foo a(argv[1]);
Foo b(argv[2]);
对象,并且让编译器处理:
{{1}}
答案 2 :(得分:4)
似乎编译器需要部分
Foo a(std::string(argv[1]));
Foo b(std::string(argv[2]));
作为函数声明。试试这个:
Foo a = std::string(argv[1]);
Foo b = std::string(argv[2]);
或澄清应该调用构造函数:
Foo a = Foo(std::string("1"));
Foo b = Foo(std::string("2"));