Date: Sat, 10 Jan 2026 13:36:59 +0100
Another disadvantage is that if you want to define the function in a
separate translation unit, you need to add an "explicit template
instantiation" (and don't forget 'extern' on the declaration...).
Modules are supposed to solve that, but they still seem to be a bit too
immature to work flawlessly everywhere...
// Robin
On Sat, Jan 10, 2026, 13:16 David Brown via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On 09/01/2026 19:49, Jonathan Wakely wrote:
> >
> >
> > On Fri, 9 Jan 2026 at 17:19, David Brown via Std-Proposals <std-
> > proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>>
> wrote:
> >
> >
> >
> > 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
> > <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.
> >
> >
> > A class seems overkill here, I would use a scoped enum type:
> >
> > enum class InterestType { Minor, Major };
> >
> > This won't allow any explicit conversions.
>
> Sure - a scoped enum is often a good alternative to a bool parameter.
> But my point was that people do make and use strong bools precisely as a
> way to stop implicit conversions. (People also make strong integer and
> floating point types that don't have implicit conversions.)
>
> The std::same_as<bool> constrained auto template is a neat solution for
> when you don't want to make a specific type (or an enum class). The
> only disadvantage I see compared to a hypothetical "explicit argument"
> is if you already had an existing definition (in another file) of the
> function with a simple "bool" parameter. The mangled function name for
> "int foo(std::same_as<bool> auto)" called with a bool argument is not
> the same as the mangled function name for "int foo(bool)". Still, if
> you retrofitting a bit of call safety to existing code, you can always
> leave the "int foo(bool)" declaration untouched and add a "int
> foo(auto...) = delete".
>
> >
> > But it seems like a badly-designed overload set anyway, since you have
> > one function name "interest" but the functions do two different things.
> > It would probably be better if you had names that make what they do
> > clearer, calc_interest_factor and calc_interest_major_minor or something
> > (I have no idea what the "minor" argument means, so better names are
> > probably possible).
> >
> >
>
> I fully agree that overloads need to be designed carefully to avoid
> confusion. I have no idea if the OP took the example from real code, or
> it was just hypothetical.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
separate translation unit, you need to add an "explicit template
instantiation" (and don't forget 'extern' on the declaration...).
Modules are supposed to solve that, but they still seem to be a bit too
immature to work flawlessly everywhere...
// Robin
On Sat, Jan 10, 2026, 13:16 David Brown via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On 09/01/2026 19:49, Jonathan Wakely wrote:
> >
> >
> > On Fri, 9 Jan 2026 at 17:19, David Brown via Std-Proposals <std-
> > proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>>
> wrote:
> >
> >
> >
> > 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
> > <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.
> >
> >
> > A class seems overkill here, I would use a scoped enum type:
> >
> > enum class InterestType { Minor, Major };
> >
> > This won't allow any explicit conversions.
>
> Sure - a scoped enum is often a good alternative to a bool parameter.
> But my point was that people do make and use strong bools precisely as a
> way to stop implicit conversions. (People also make strong integer and
> floating point types that don't have implicit conversions.)
>
> The std::same_as<bool> constrained auto template is a neat solution for
> when you don't want to make a specific type (or an enum class). The
> only disadvantage I see compared to a hypothetical "explicit argument"
> is if you already had an existing definition (in another file) of the
> function with a simple "bool" parameter. The mangled function name for
> "int foo(std::same_as<bool> auto)" called with a bool argument is not
> the same as the mangled function name for "int foo(bool)". Still, if
> you retrofitting a bit of call safety to existing code, you can always
> leave the "int foo(bool)" declaration untouched and add a "int
> foo(auto...) = delete".
>
> >
> > But it seems like a badly-designed overload set anyway, since you have
> > one function name "interest" but the functions do two different things.
> > It would probably be better if you had names that make what they do
> > clearer, calc_interest_factor and calc_interest_major_minor or something
> > (I have no idea what the "minor" argument means, so better names are
> > probably possible).
> >
> >
>
> I fully agree that overloads need to be designed carefully to avoid
> confusion. I have no idea if the OP took the example from real code, or
> it was just hypothetical.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2026-01-10 12:37:16
