<div dir="ltr"><div dir="ltr">On Wed, Aug 25, 2021 at 9:04 AM Brian Cain via libcxx-dev <<a href="mailto:libcxx-dev@lists.llvm.org">libcxx-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





<div lang="EN-US" style="overflow-wrap: break-word;">
<div class="gmail-m_4499219610870046716WordSection1">
<p class="MsoNormal">For the test case below, clang++-12 does not emit an error (likely the same on ToT).  Nor does g++-9.4.0 with libstdc++.  But should they?</p></div></div></blockquote><div><br></div><div>No. Why do you wonder if they should?</div><div>std::variant construction works by "fictitious overload set": it goes basically as if you'd written</div><div>    void f(int);</div><div>    void f(S<A>);</div><div>    ... f(1); ...</div><div><br></div><div>In the fictitious overload resolution, the `int` argument is a better match for `f(int)` than for `f(S<A>)`, so `f(int)` is chosen. Back in the real world, that means that the variant `b` is initialized via its `int` alternative, not its `S<A>` alternative.</div><div>However, this does turn out to get weird when it comes to narrowing conversions, and I haven't investigated the wording to find out why. Basically</div><div><div>    std::variant<int, S<A>> b(int(1));  // initializes the `int`, duh</div><div><div>    std::variant<int, S<A>> b(short(1));  // initializes the `int`</div><div><div><div>    std::variant<int, S<A>> b(char(1));  // initializes the `int`</div><div><div>    std::variant<int, S<A>> b(long(1));  // initializes the `S<A>` !?!?!</div><div>even though a call to `f(long(1))` would resolve to `f(int)`, not `f(S<A>)`.</div></div></div></div></div></div><div><br></div><div>Finally, btw, note that you wrote `S(T&&...)` instead of `S(T&&)`. Surprisingly, this is valid C++ syntax, because a trailing `...` can mean variadic-function ellipsis instead of parameter-pack-expansion; it's exactly as if you wrote</div><div>    S(T&&, ...) {}</div><div>Since you're passing only one argument anyway, the trailing ellipsis matches no arguments, contributes nothing to overload resolution, and therefore doesn't matter at all.</div><div><br></div><div>HTH,</div><div>Arthur</div></div></div>