Consider the following:
#include <iostream>
#include <variant>
int main ()
{
std::variant<int, float> foo = 3;
if(foo == 3)
{
std::cout << "Equals 3\n";
}
}
This does not compile because of the foo == 3
:
<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.
CodePudding user response:
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.
CodePudding user response:
There is no implicit conversion from the type int
to the type std::variant<int, float>
.
Use for example
if( std::get<int>( foo ) == 3)