C ++编译错误构造具有rvalue std :: string的对象 [英] C++ compile error constructing object with rvalue std::string

查看:134
本文介绍了C ++编译错误构造具有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆