Date: Thu, 7 Dec 2023 11:15:43 +0600
Hello!
std::optional<T> has a really greedy converting constructor. It accepts
almost any type that T is constructible from, and constructs a T from
it, even if that type is also convertible to optional<T>. Example:
https://gcc.godbolt.org/z/ncsYehW19
#include <iostream>
#include <optional>
#include <source_location>
struct A
{
template <typename T>
operator T()
{
std::cout <<
std::source_location::current().function_name() << '\n';
return {};
}
};
int main()
{
std::optional<int> x(A{}); // (1) Calls `operator int`, not
`operator optional<int>`.
// std::optional<int> y = A{}; // (2) Ambiguous.
x = A{}; // (3) Calls `operator int`, not `operator optional<int>`.
}
This is very confusing in my eyes. std::optional is first type I see in
the wild that doesn't play nice with templated conversion operators.
I suggest we make this constructor of optional not participate in
overload resolution if the argument is convertible to optional<T>.
This would make (2) valid, and make all three lines call A::operator
optional<T>.
std::optional<T> has a really greedy converting constructor. It accepts
almost any type that T is constructible from, and constructs a T from
it, even if that type is also convertible to optional<T>. Example:
https://gcc.godbolt.org/z/ncsYehW19
#include <iostream>
#include <optional>
#include <source_location>
struct A
{
template <typename T>
operator T()
{
std::cout <<
std::source_location::current().function_name() << '\n';
return {};
}
};
int main()
{
std::optional<int> x(A{}); // (1) Calls `operator int`, not
`operator optional<int>`.
// std::optional<int> y = A{}; // (2) Ambiguous.
x = A{}; // (3) Calls `operator int`, not `operator optional<int>`.
}
This is very confusing in my eyes. std::optional is first type I see in
the wild that doesn't play nice with templated conversion operators.
I suggest we make this constructor of optional not participate in
overload resolution if the argument is convertible to optional<T>.
This would make (2) valid, and make all three lines call A::operator
optional<T>.
Received on 2023-12-07 05:15:48