Why does reference_wrapper<string> comparison not work?

175 Views Asked by At
int main()
{
    int x = 1;
    auto ref = std::ref(x);
    if (x < ref)
    {
        ...
    }
}

In the above code, I made an int variable and a reference_wrapper<int> variable, and then compared them, and it works well.

However, If I change the type int to string, It raises a compile error like this.

binary '<': 'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator

I thought that reference_wrapper<string> would be implicitly converted to string, but wouldn't.
Are there any rules that prevent implicit conversion from reference_wrapper<string> to string?

3

There are 3 best solutions below

0
On BEST ANSWER

std::reference_wrapper<> more or less supports only one operation: an implicit type conversion back to the original type (which is std::string in your case).

But the problem is that the compiler has to know that an implicit conversion back to the original type is necessary.

That is why your example works with the built-in type int, while not with the class template instantiation std::string of the basic_string class template.

The situation is similar to the below given example:

template<typename T>
struct MyWrapper 
{
    operator T()
    {
        return T{};
    }
};
int main()
{
    int x = 1;
    MyWrapper<int> ref;
    
    if(x < ref)  //WORKS WITH INT
    {
        
    }
    
    std::string x2 = "f";
    MyWrapper<std::string> ref2;
    
    if(x2 < ref2)  //WON'T WORK WITH STD::STRING
    {
        
    }
    
}

To solve this problem, we need to explicitly say that we want the original type, which we can do by using the get() member function, as shown below:

std::string x = "hi";
auto ref = std::ref(x);
//----------vvvvv------->get() member function used here
if (x < ref.get())
{
        
}
1
On

My guess is because std::string is a template instantiation of std::basic_string and therefor when it tries to call the operator it can't find an exact match. link to std::string operator definitions

0
On

Use std::reference_wrapper<T>::get for explicit conversion.

int is a primitive data type, while string is a template type as mentioned by Tyler Wojciechowski.


Illustration

int main()
{
    string x = "hi";
    auto ref = std::ref(x).get();
    if (x < ref)
    {
        ...
    }
}