返回值和局部变量之间的区别

假设我有

#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:bitbucketvxprojectsplasma4testplasma4test.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:bitbucketvxprojectsplasma4testplasma4test.cpp(36): error C2593: 'operator =' is ambiguous
1>          c:program filesmicrosoft visual studio 10.0vcincludexstring(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 filesmicrosoft visual studio 10.0vcincludexstring(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 filesmicrosoft visual studio 10.0vcincludexstring(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:bitbucketvxprojectsplasma4testplasma4test.cpp(37): error C2593: 'operator =' is ambiguous
1>          c:program filesmicrosoft visual studio 10.0vcincludexstring(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 filesmicrosoft visual studio 10.0vcincludexstring(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 filesmicrosoft visual studio 10.0vcincludexstring(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 filesmicrosoft visual studio 10.0vcincludexstring(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的bug,它 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 )的所有可用转换序列,那么涉及到A的用户定义转换函数到char const*转换序列需要进一步转换(通过B的构造函数接受一个char const* )以达到目标类型 B 因此,它比使用A的用户定义的转换函数B (按照13.3.3.2)更长一步,这使得后者更可取。

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

链接地址: http://www.djcxy.com/p/11731.html

上一篇: Difference between return value and local variable

下一篇: C encoding of character constants