c++ - 返回值和局部变量的区别

标签 c++ constructor return-value local-variables conversion-operator

假设我有

#include <string>

class A
{
public:
    template<class T>
    operator T();

    A child();
};

void f()
{
    A a;
    std::string s1 = a;            // ok
    std::string s2 = a.child();    // error (line 34)

    s1 = a;           // error (line 36)
    s2 = a.child();   // error (line 37)

}

std::string 构造函数可以采用 char* 或 std::string 引用,这就是赋值不明确的原因。但为什么我的编译器 (VC++10) 提示第二个赋值而不是第一个?

我正在寻找一种方法让模板转换运算符优先于重载的构造函数。

我收到以下错误:

1>------ Build started: Project: Plasma4Test, Configuration: Debug Win32 ------
1>  Plasma4Test.cpp
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(34): error C2440: 'initializing' : cannot convert from 'A' to 'std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(36): error C2593: 'operator =' is ambiguous
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(772): could be 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(_Elem)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(767): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const _Elem *)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(762): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const std::basic_string<_Elem,_Traits,_Ax> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          while trying to match the argument list '(std::string, A)'
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(37): error C2593: 'operator =' is ambiguous
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(772): could be 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(_Elem)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(767): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const _Elem *)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(762): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const std::basic_string<_Elem,_Traits,_Ax> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(707): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(std::basic_string<_Elem,_Traits,_Ax> &&)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          while trying to match the argument list '(std::string, A)'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

最佳答案

对我来说这似乎是一个 VC10 错误,并且它与 std::string 不相关

错误隔离:

我把它归结为以下示例:

#include <string>

class B
{
public:
    B(char const*) { }
    B(B&&) { }
};

class A
{
public:
    operator char* const () { return 0; }
    operator B () { return B(0); }
};

int main()
{
    A a;
    B b1 = a; // fine
    B b2 = A(); // error C2440: 'initializing' : cannot convert from 'A' to 'B'
                // No constructor could take the source type, or constructor
                // overload resolution was ambiguous.
}

B 类有一个移动构造函数和一个采用const char* 的构造函数。当尝试从 rvalue 初始化 b2 时,VC10 似乎无法选择到 B 的转换运算符。

Clang 3.2 和 GCC 4.7.2 都将转换运算符选择为 B

C++ 标准规则:

C++ 标准第 8.5/16 段要求:

[对于这种复制初始化的情况,] “用户定义的转换序列,可以从源类型转换为目标类型或(当使用转换函数时)到其派生类如 13.3.1.4 中所述进行枚举,并通过重载决议(13.3)选择最佳的“

如果我们考虑示例中所有可用的转换序列,从源类型 (A) 到目标类型 (B),那么涉及 Achar const* 的用户定义转换函数需要进一步转换(通过 B 的构造函数完成接受 char const*) 以到达目标类型 B。因此,它比使用A的用户自定义转换函数到B(根据13.3.3.2)多了一步,这使得后者更可取。

这似乎证实了这是一个 VC10 错误。

关于c++ - 返回值和局部变量的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14379295/

相关文章:

c++ - 释放STL占用的空间

c++ - Eigen 3.2.1 + MKL = C4244 编译器警告

c++ - 从 C++ 中的动态库访问静态类成员

java - 从子类构造函数调用 super 构造函数是否会在内存中创建父类(super class)的对象?

c++ - 我可以在类的构造函数中使用枚举吗?

php - Yii Joined table 但不是所有选定的数据都被检索

c++ - OpenCV 切槽检测

java - 调用 Fragment 的空构造函数而不是 newInstance

c# - 如何在后续方法中引用方法返回值?

debugging - 是否可以根据函数即将返回的内容在函数末尾设置条件断点?