Date: Fri, 9 Jan 2026 18:18:48 +0100
On 09/01/2026 17:37, Steve Weinrich via Std-Proposals wrote:
> Consider two methods:
>
> void interest (double arg1, bool minor);
>
> void interest (double arg1, int factor);
>
> The call: interest(5.5, 5); is ambiguous because 5 will freely convert
> to a bool.
No, it is not ambiguous - the best fit overload will be used. The rules
for overload resolution are a bit complicated, but in this case the
results are clear.
<https://en.cppreference.com/w/cpp/language/overload_resolution.html>
>
> I was wondering what y’all would think of narrowing this behavior by
> this addition:
>
> void interest (double arg1, *explicit* bool minor);
>
> Potentially, this could be applied to all arguments:
>
> void *explicit* interest (double arg1, bool minor);
>
To me, a bigger issue is when you /don't/ have overloads :
void interest (double arg1, bool minor);
In this situation, the implicit conversion of an int to a bool for
"interest(5.5, 5)" is likely to be an error on the programmer's side,
but it is accepted without question by C++ compilers. To avoid this,
some people use "strong bool" types that have much stricter implicit
conversions, such as :
class Bool {
bool v;
public :
constexpr Bool(bool v) noexcept : v(v) {}
Bool(auto v) = delete;
explicit constexpr operator bool() const noexcept { return v; }
};
Then you can declare the function :
void interest (double arg1, Bool minor);
and use it with a bool type as the second argument, but not with another
type that has an implicit conversion to bool.
An alternative way to block non-bool calls would be to write :
void interest (double arg1, bool minor);
void interest (double arg1, auto) = delete;
But it would be very nice (IMHO) if you could just write :
void interest (double arg1, explicit bool minor);
and get the same effect (that is, a function candidate would not be
considered "viable" in overload resolution if the second argument
required an implicit conversion sequence to the specified type).
> Consider two methods:
>
> void interest (double arg1, bool minor);
>
> void interest (double arg1, int factor);
>
> The call: interest(5.5, 5); is ambiguous because 5 will freely convert
> to a bool.
No, it is not ambiguous - the best fit overload will be used. The rules
for overload resolution are a bit complicated, but in this case the
results are clear.
<https://en.cppreference.com/w/cpp/language/overload_resolution.html>
>
> I was wondering what y’all would think of narrowing this behavior by
> this addition:
>
> void interest (double arg1, *explicit* bool minor);
>
> Potentially, this could be applied to all arguments:
>
> void *explicit* interest (double arg1, bool minor);
>
To me, a bigger issue is when you /don't/ have overloads :
void interest (double arg1, bool minor);
In this situation, the implicit conversion of an int to a bool for
"interest(5.5, 5)" is likely to be an error on the programmer's side,
but it is accepted without question by C++ compilers. To avoid this,
some people use "strong bool" types that have much stricter implicit
conversions, such as :
class Bool {
bool v;
public :
constexpr Bool(bool v) noexcept : v(v) {}
Bool(auto v) = delete;
explicit constexpr operator bool() const noexcept { return v; }
};
Then you can declare the function :
void interest (double arg1, Bool minor);
and use it with a bool type as the second argument, but not with another
type that has an implicit conversion to bool.
An alternative way to block non-bool calls would be to write :
void interest (double arg1, bool minor);
void interest (double arg1, auto) = delete;
But it would be very nice (IMHO) if you could just write :
void interest (double arg1, explicit bool minor);
and get the same effect (that is, a function candidate would not be
considered "viable" in overload resolution if the second argument
required an implicit conversion sequence to the specified type).
Received on 2026-01-09 17:18:53
