feuGene
feuGene

Reputation: 4001

Compiler error in VC++2010 (clean in 2008!), "ambiguous call to overloaded function"

I'm hitting a compile error in VS2010 with code that compiles cleanly in VS2008.

Here's my error, from the Output Window, with all of its verbosity:

...\elementimpl.h(49): error C2668: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string' : ambiguous call to overloaded function
      with
      [
          _Elem=char,
          _Traits=std::char_traits<char>,
          _Ax=std::allocator<char>
      ]
      c:\program files (x86)\microsoft visual studio 10.0\vc\include\xstring(700): could be 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(std::basic_string<_Elem,_Traits,_Ax> &&)'
      with
      [
          _Elem=char,
          _Traits=std::char_traits<char>,
          _Ax=std::allocator<char>
      ]
      c:\program files (x86)\microsoft visual studio 10.0\vc\include\xstring(590): or       'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const _Elem *)'
      with
      [
          _Elem=char,
          _Traits=std::char_traits<char>,
          _Ax=std::allocator<char>
      ]
      while trying to match the argument list '(CXStr)'

and here's the code in error, elementimpl.h(49):

    std::string getAttributeValue(const char* attr) { return getAttribute(CXStr(attr)); }

getAttribute() returns a CXStr (an ADT), which obviously no std::string constructor accepts, so it needs to convert the CXStr to something suitable.

CXStr can be converted to either a std::string or a char*:

class CXStr
{
public:
    ...
    CXStr(std::string);
    CXStr(const char* ch);

    const CXStr& operator=(const char*);
    const CXStr& operator=(std::string&);

    operator char*();
    operator std::string(); 
    ...
}

When I run through the debugger in VS2008, I can see that it goes through "CXStr::operator std::string()" after getAttribute(), and then it goes through the std::string copy constructor to create the object to be returned by getAttributeValue(). I want my 2010 build to behave the same way.

My questions:

Upvotes: 2

Views: 1440

Answers (2)

Christopher
Christopher

Reputation: 8992

The problem is, that VS2010 added move constructors and your implementation falls directly into this hole.

Previously there was only one constructor, the const char* one, which was available to the std::string constructor. Now there is the move constructor, too.

I really think a design relying on implicit conversions is dangerous. Thats why all one parameter constructors should be explicit ...

I think you should discourage the use of implicit operators, because they lead to bad overloads being used. If you cannot do that, wrap the currently failing calls into an explicit conversion call std::string( CXStr( x ).toString() ). There can be other errors which are hidden by using 'non-explicit' cast operators ... .

Upvotes: 3

Edward Strange
Edward Strange

Reputation: 40895

Why haven't you tried commenting out operator std::string() yet?

You could also explicitly cast your CXStr to std::string.

Frankly though, I can't see the use of this CXStr thing. What, if anything, does it provide in the way of services?

Upvotes: 0

Related Questions