I have something along the lines of:
#include <iostream>
class Foo;
struct Test
{
template <typename T>
operator T() const // <----- This const is what puzzles me
{
std::cout << "Template conversion" << std::endl;
return T{};
}
operator Foo*()
{
std::cout << "Pointer conversion" << std::endl;
return nullptr;
}
};
int main()
{
Test t;
if (t)
{
std::cout << "ahoy" << std::endl;
}
bool b = (bool)t;
Foo* f = (Foo*)t;
}
It builds fine, but when I run it, while I would expect to get
$> ./a.out
Template conversion
Template conversion
Pointer conversion
I instead get
$> ./a.out
Pointer conversion
Pointer conversion
Pointer conversion
If I remove the const, or make the Test instance const, then everything works as expected. More precisely, the overload selection seems to make sense strictly when both operators have the same const qualification.
13.3.3.1.2 point of the standard makes me think I should get an identity conversion, converting to a bool, using the template conversion operator instantiation with a T
= bool
, though there is obviously a subtlety hiding somewhere. Could someone enlighten me as to what rule comes into play here?