10

Consider the following code.

#include <iostream>
#include <string>

struct SimpleStruct
{
    operator std::string () { return value; }
    std::string value;
};

int main ()
{
    std::string s;    // An empty string.
    SimpleStruct x;   // x.value constructed as an empty string.

    bool less = s < x; // Error here.
    return 0;
}

This code does not compile either on g++ or Microsoft Visual C++. The error report given by compilers is no match for operator '<' in 's < x'. The question is why does the compiler not simply convert the SimpleStruct x to string according to the given operator string () and then use operator < ( string, string )?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Grigor Gevorgyan
  • 6,753
  • 4
  • 35
  • 64

1 Answers1

13

operator< for std::string is a function template. The overloads are:

  template<class charT, class traits, class Allocator>
    bool operator< (const basic_string<charT,traits,Allocator>& lhs,
            const basic_string<charT,traits,Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    bool operator< (const basic_string<charT,traits,Allocator>& lhs,
            const charT* rhs);
  template<class charT, class traits, class Allocator>
    bool operator< (const charT* lhs,
            const basic_string<charT,traits,Allocator>& rhs);

Your call doesn't match any of the available overloads, so they are all removed from a list of candidates. Since no function template was picked as a candidate for resolving the call, there is nothing to convert SimpleStruct to.

template <class T>
class String
{
};

template <class T>
bool operator< (const String<T>&, const String<T>&) { return true; }


//if a suitable non-template function is available, it can be picked
//bool operator< (const String<char>&, const String<char>&) { return true; }

struct SimpleStruct
{
   operator String<char> () { return value; }
   String<char> value;
};

int main()
{
    String<char> s;
    SimpleStruct ss;
    s < ss; //the call doesn't match the function template, leaving only the commented-out candidate
}
visitor
  • 1,781
  • 10
  • 7
  • 1
    +1, this answer is correct. `string::operator <()` doesn't take argument as `const string&`, but `basic_string<>`; if you overload `operator <` globally then it works. http://www.ideone.com/vMERa – iammilind Jul 22 '11 at 10:08
  • 1
    Eh, `std::string` is just a typedef for `std::basic_string`. `typedef` doesn't introduce a new type, and therefore doesn't affect overloading. – MSalters Jul 22 '11 at 11:49
  • 2
    The underlying problem is that the deduction of `charT` in `template bool operator< (std::basic_string const& lhs, std::basic_string const& rhs);` fails. There's no `charT` for which `basic_string` _equals_ `SimpleStruct`. That indeed removes it from the overload set. – MSalters Jul 22 '11 at 11:55