In the following code
struct S {
operator auto() { return 42; }
};
operator auto
is equivalent to operator int
since actual type would be deduced from the literal 42
and that type is int
. If I write 42.5
instead of 42
then operator auto
would be interpreted as operator double
for obvious reason. But when I use both at the same time I got a compiler error for all three major compilers (gcc, clang, msvc):
struct S {
operator auto() { return 42; }
operator auto() { return 42.5; }
};
Actual error messages are vary among compilers, but the reason is the same: "Function already defined".
I can't find in standard why the both operator auto
(with different return type) can't be used simultaneously in one class. Could someone point me to the standard's clause where that set of conversion functions considered as forbidden?
If you need just two or three operator auto
s in a class, then the trick with const
and decltype(auto)
will work for you:
#include <iostream>
struct S
{
operator auto() { return 42; }
operator const auto() { return 42.5; }
operator decltype(auto)() { return 43.5f; }
};
int main()
{
S s;
std::cout << (int)s << '\n';
std::cout << (double)s << '\n';
std::cout << (float)s << '\n';
}
https://gcc.godbolt.org/z/hvbesaM4z
Unfortunately, it does not work for more than three distinct operators. It is the limitation of the current C++.
Based on idea from Fedor's answer you can even use at least 12 auto
like operators with different qualifiers:
#include <iostream>
struct S {
operator auto() { return 42; }
operator auto() const { return '+'; }
operator auto() volatile { return 44LL; }
operator const auto() { return 45.5; }
operator const auto() const { return 46.5f; }
operator const auto() volatile { return 47L; }
operator volatile auto() { return 48ULL; }
operator volatile auto() const { return 49U; }
operator volatile auto() volatile { return 50UL; }
operator decltype(auto)() { return 51.5L; }
operator decltype(auto)() const { return 52.5L; }
operator decltype(auto)() volatile { return 53.5L; }
};
int main() {
const S s;
std::cout << (int)(S)s << "\n";
std::cout << (char)s << "\n";
std::cout << (long long)(volatile S)s << "\n";
std::cout << (double)(S)s << "\n";
std::cout << (float)s << "\n";
std::cout << (long)(volatile S)s << "\n";
std::cout << (unsigned long long)(S)s << "\n";
std::cout << (unsigned)s << "\n";
std::cout << (unsigned long)(volatile S)s << "\n";
std::cout << (long double)(S)s << "\n";
std::cout << (long double)s << "\n";
std::cout << (long double)(volatile S)s << "\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With