Question

I am "porting" a multiplatform project code from VS2003 to VS2013.

I hit an error that I cannot understand.

Here's a test code that illustrates it:

using namespace std;

class MyString : public string {

public:

    MyString() : string() {};
    MyString(const string   &a_path) : string(a_path) {};
    MyString(const MyString &a_path) : string(a_path) {};

    friend MyString operator+(const MyString& path, const string& s) {
        string str(path);
        return str + s;
    }; 
};

void test() {

    MyString result;
    MyString one;

    result = one + string("aaa"); // error C2666 } }

This code can be compiled with VS2003 and several (newer) versions of gcc. The VS2013 compiler complains with the following error:

1>mystring.cpp(22): error C2666: 'operator +' : 3 overloads have similar conversions
1>mystring.cpp(12): could be 'MyString operator +(const MyString &,const std::string &)' [found using argument-dependent lookup] 
1>    [...]\xstring(2411): or  'std::basic_string<char,std::char_traits<char>,std::allocator<char>> std::operator +<char,std::char_traits<char>,std::allocator<char>>(std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&)' 
1>    [...]\xstring(2401): or  'std::basic_string<char,std::char_traits<char>,std::allocator<char>> std::operator +<char,std::char_traits<char>,std::allocator<char>>(std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&,const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)' 
1>    [...]\xstring(2391): or  'std::basic_string<char,std::char_traits<char>,std::allocator<char>> std::operator +<char,std::char_traits<char>,std::allocator<char>>(const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&)' 
1>    [...]\xstring(2321): or  'std::basic_string<char,std::char_traits<char>,std::allocator<char>> std::operator +<char,std::char_traits<char>,std::allocator<char>>(const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &,const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)' 
1>    while trying to match the argument list '(MyString, std::basic_string<char,std::char_traits<char>,std::allocator<char>>)' 
1>    note: qualification adjustment (const/volatile) may be causing the ambiguity

The class in my project is one of basic classes and is used in whole project. So I am looking for a solution that would not affect a lot of code.

Was it helpful?

Solution 2

The correct solution to the problem would be to implement the operator with different arguments.

So the operator declaration should be:

MyString operator+(const string& path, const string& s);

instead of:

MyString operator+(const MyString& path, const string& s);

This could be a problem if its implementation would need to access some functionality of class MyString. But that is not true in my case.

Thanks to @Arne Mertz to point me to the right direction.

OTHER TIPS

Given the current code you need not (and that means should not) make the operator a friend of your class, because it does not need access to private members:

class MyString : public string {

public:

    MyString() : string() {};
    MyString(const string   &a_path) : string(a_path) {};
    MyString(const MyString &a_path) : string(a_path) {};
};

MyString operator+(const MyString& path, const string& s) {
    string str(path);
    return str + s;
}; 

However, while this might solve your problem, I should mention that standard library classes like std::string are not meant to be derived from, so you should consider other means (e.g. aggregation instead of inheritance) to achieve your goal. That will probably help to solve your problem, too, because the compiler will not consider MyString to be a std::string and get confused by the overloads available.

In addition, I hope the using directive right before the class' definition is just for the sake of brevity, becuase using directives on namespace scope in a header are very seldom a good thing to do.

update: looking more closely at the implementation of the operator+, you might want to leave it out completely, since it does what the operator+ taking two std::string's already does for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top