0

I have a class with several constructors and overloaded operators :

class Utf8String
{
public:

   Utf8String();

   explicit Utf8String( const char * sStr );

   Utf8String( const char * sStrBeg, const char * sStrEnd );

   Utf8String( const char * sStr, uint32_t nCpCount );

   explicit Utf8String( const Utf8String & sStr );

   explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

   Utf8String( uint32_t nCpCount, uchar32_t cCodePoint );

   explicit Utf8String( long int iVal );

   explicit Utf8String( double fVal );

   // More stuff

   inline Utf8String operator + ( const char * sStr ) const
   {
      Utf8String sRes( *this ); // ERROR
      return sRes += sStr;
   }

   inline operator const char * () const;

   inline operator char * ();

   inline operator long int () const;

   inline operator double () const;
};

For some reason i'm getting an error :

Error   3   error C2668: 'core::Utf8String::Utf8String' : ambiguous call to overloaded function c:\xxx\utf8string.h 280

I tried added explicit keywords where it seemed to make sense. I also added explicit to all constructors, just to see what happens, but no matter what i do i'm getting this error and can' figure out why.

Do you have an idea ? Thank you.

Virus721
  • 8,061
  • 12
  • 67
  • 123
  • 1
    Which line is `utf8string.h 280`? – timrau May 22 '15 at 08:19
  • The one with the `// ERROR` comment, and also the only one containg implementation code. – Virus721 May 22 '15 at 08:20
  • You are getting the error because two constructors match the call. `Utf8String(const Utf8String& sStr)` and `Utf8String(const Utf8String& sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX)` are both good candidates. This is not allowed. You need to define one copy constructor, not two. – n. m. could be an AI May 22 '15 at 08:25

2 Answers2

3

These two functions:

explicit Utf8String( const Utf8String & sStr );

explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

should not exist at the same time. They cause the issue.

Since the rest of the arguments of the second constructor has default values, they would cause ambiguous error if you pass just one argument, as shown below:

 Utf8String s = get_utfString();

 Utf8String s1(s); //which above constructor should be called?

One fix would be : remove the default values for the second constructor.

Also, these constructor are copy-constructor, and therefore, explicit doesn't make much sense. You would use explicit to avoid implicit version from one type X to another type Y. In this case, avoiding implicit conversion from Utf8String const& to Utf8String doesn't make sense, as such conversion wouldn't really cause issue (if it does, then the problem is likely to be in the other parts of your code).

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Thanks for your help. I'm not sure to understand why explicit does not make sense on the copy constructor. Could you explain please ? – Virus721 May 22 '15 at 08:30
  • @Virus721: Added the explanation for that. – Nawaz May 22 '15 at 08:34
  • Okay. And i would have another question of the same kind if u want. Imagine that i have a method `Foo( const Utf8String & )` and a method `Foo( const char * )`. Since a Utf8String can be converted to both `const Utf8String &` and `const char *`, am i not going to get problems with this method Foo ? Can't i use explicit on methods too ? Thank you. – Virus721 May 22 '15 at 08:39
  • @Virus721: Try. Explore. Read about `explicit` more. See more examples. – Nawaz May 22 '15 at 08:40
1

Your following two constructors can both serve as a copy constructor:

explicit Utf8String( const Utf8String & sStr );
explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

each of them matches the Utf8String( const Utf8String & sStr ) signature. This is what compiler does not like.

You should really think which of two constructors do you want to use as a copy constructor. If it is the first one, then drop the default value for nStart in the second constructor. If it is the second, then drop the first constructor entirely.

In fact, I assume that your second constructor just takes a substring and therefore called without nStart and nCpCount arguments will work exactly as a copy constructor is expected to work. So the simplest way will be just drop the first constructor of these pair.

However, this might lead to some (mostly perfomance) problems depending on your representation of Utf8String, so that's up to you to decide.

Petr
  • 9,812
  • 1
  • 28
  • 52
  • I'll just remove the default value for nStart to keep two separate constructors, for performance reasons as you guessed it. Thanks for your help. – Virus721 May 22 '15 at 08:29