[cfe-dev] A question about templates and best viable functions

Richard Smith richard at metafoo.co.uk
Sun Sep 14 18:59:23 PDT 2014


On Tue, Sep 9, 2014 at 9:16 AM, Sebastian Redl <
sebastian.redl at getdesigned.at> wrote:

>
> On 09 Sep 2014, at 17:24, Samuele Panzeri <samuele.panzeri at gmail.com>
> wrote:
>
> > Hi,
> >
> > I was experimenting some code and I incurred in an unexpected error.
> > I reduce the code to the minimal case:
> >
> > template <class T>
> > struct MyStruct {
> >       operator float* () { return 0; }
> >       operator T* () { return 0; }
> > };
> > void func(bool) {}
> > void func(int*) {}
> > int main() {
> >       MyStruct<int> x;
> >       func(x);
> > }
>
> This isn’t minimal. There’s no need for the template; this code yields the
> same results (in Clang, at least):
>
> struct MyStruct {
>         operator float* () { return 0; }
>         operator int* () { return 0; }
> };
> void func(bool) {}
> void func(int*) {}
> int main() {
>         MyStruct x;
>         func(x);
> }


This gives a rather different problem. In the original question, we had

MyStruct -> float* -> bool -> void func(bool)
MyStruct -> T* (T = int) -> void func(int*)

(Note that we can't use the template for the bool overload of func, because
we cannot deduce T.) In your version, we have an ambiguous conversion
sequence for MyStruct and a user-defined conversion sequence for func(int*).

In the original version, the reason for ambiguity is that user-defined
conversion sequences with different conversion functions are incomparable.
(See 13.3.3.2/3.2.)


> >
> > Now, I was wondering which one is the expected behaviour according to
> the standard.
> > From 13.3.3 (Best Viable Function):
> >
> > — the context is an initialization by user-defined conversion (see 8.5,
> 13.3.1.5, and 13.3.1.6) and the
> >     standard conversion sequence from the return type of F1 to the
> destination type (i.e., the type of the
> >     entity being initialized) is a better conversion sequence than the
> standard conversion sequence from
> >     the return type of F2 to the destination type
>
> This bullet point doesn’t apply. The context that is ambiguous is the
> function call func(x), not the decision between the two conversion
> operators (that’s a separate, nested overloading decision while determining
> the conversion sequences for each of the two variants of func).
>
> >
> > In this case both the function call require user defined conversion.
> >
> > The one using non-template parameter yield to a standard conversion
> sequence of type boolean conversion (4.12).
> >
> > The UDC with a template parameter should resolve in a user defined
> conversion followed by a standard conversion of identity type (exact match).
> >
> > Intuitively I would expect this second conversion to be considered a
> better match than the latter one and be selected.
>
> I agree that it is intuitive, but let’s look at it more formally.
>
> When the compiler sees func(x), it has to decide between calling
> func(bool) and func(int*). The argument in either case is of type MyStruct.
> To decide, it individually finds the conversion sequences for all
> parameters of all candidates.
>
> func(bool) can be called in two ways: MyStruct->int*->bool and
> MyStruct->float*->bool. Since neither is better than the other, the
> conversion is the “ambiguous conversion sequence” (13.3.3.1p10), which "is
> treated as a user-defined sequence that is indistinguishable from any other
> user-defined conversion sequence”.
>
> func(int*) can be called in one way: MyStruct->int*. This is a
> user-defined conversion sequence.
>
> Since the ACS for func(bool) is, by definition, indistinguishable from the
> UDCS for func(int*), the call is ambiguous. Clang and GCC are correct, MSVC
> is wrong.
>
> This case is an unfortunate casualty of preventing a more dangerous
> unintuitive situation, as described in the footnote referenced by my quoted
> standard paragraph. Making this particular case work again would require
> that the ambiguous conversion sequence somehow keep its trailing standard
> conversion sequences around (or at least the best one) for the purpose of
> comparing it to the trailing standard conversion sequence in other
> overloads - a significant increase in complexity for overload resolution.
>
> Sebastian
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140914/3fdcdd32/attachment.html>


More information about the cfe-dev mailing list