Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does operator==(std::variant<T, U>, T) not work?

Consider the following:

#include <iostream>
#include <variant>

int main ()
{
    std::variant<int, float> foo = 3;
    if(foo == 3)
    {
        std::cout << "Equals 3\n";
    }
}

Godbolt demo here

This does not compile because of the foo == 3:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<source>:7:12: error: no match for 'operator==' (operand types are 'std::variant<int, float>' and 'int')
    7 |     if(foo == 3)
      |        ~~~ ^~ ~
      |        |      |
      |        |      int
      |        std::variant<int, float>
In file included from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iosfwd:40,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ios:38,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ostream:38,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iostream:39,
                 from <source>:1:
/opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/postypes.h:192:5: note: candidate: 'template<class _StateT> bool std::operator==(const fpos<_StateT>&, const fpos<_StateT>&)'
  192 |     operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs)
      |     ^~~~~~~~
// Many, many more rejected operator== candidates omitted

There’s a free function operator== that compares two std::variant<int, float>s. And there’s an implicit conversion from int to std::variant<int, float>; that’s how I was able to initialize foo in the first place. So why doesn’t this comparison compile?

Strictly speaking, I suppose there are a few related questions here. One is why this doesn’t already work, explaining how the rules for overload resolution apply to this section. And second is if there’s anything that can be done in user-written code to make this comparison work sensibly.

>Solution :

Neither parameter of that operator== overload is an undeduced context. So template argument deduction for the overload will fail if it fails in either parameter/argument pair.

Since int is not a std::variant, deduction will fail for the corresponding parameter/argument pair and so the template overload is not viable.

Implicit conversions are not considered when deducing template arguments. Types must (with few minor exceptions) match exactly.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading