<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Fri, Apr 5, 2019 at 7:46 PM Alexander Us via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-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-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div>Hi,<br><br>While experimenting with some heavily templated code I have faced with some problems. First of all, I do not understand whether my code should be compiled at all (because of processing of trailing parameters packs) and I have found nothing about it in C++17 standard draft. I tried 4 different compilers (with different front-ends) on godbolt: gcc, clang, icc, msvc.<br></div></blockquote><div><br></div><div>This seems like a question that would be more suited to posting on the cpplang Slack or StackOverflow, rather than cfe-dev specifically (since it has nothing directly to do with the Clang front-end but is a question about C++ in general).</div><div>However...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div>1) First question is about variadic templates and how they are expanded. Consider the following code:<br><br><span style="font-family:"andale mono",times">template<typename A> struct S {};<br><br>template<typename T, typename...Rest><br>using U = S<T, Rest...>; // is it valid?<br><br>using SI = U<int>; // seems, that there should be S<int> and there is nothing ill-formed</span><br><br>The problem here is that only gcc (starting from version 7.1) is able to compile this code. Other compilers report that using directive is ill-formed because it provides too many template parameters for S. Who is right in this case?<br></div></blockquote><div><br></div><div>My understanding is that all four compilers' behavior is correct. Template `U` is well-formed <b><i>only </i></b>when Rest... is an empty pack, and thus the program is ill-formed (no diagnostic required) via <a href="http://eel.is/c++draft/temp.res#8.3">http://eel.is/c++draft/temp.res#8.3</a>.  So technically any behavior at all is conforming to the standard. (This doesn't mean the compiler's behavior couldn't be made more user-friendly! An enhancement request might still be warranted.)</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div>2) Second example is quite more complicated. The code is:<br><br><span style="font-family:"andale mono",times">template<typename A, typename B> struct S {};<br><br>template<template<typename...> typename F><br>struct Flip {<br>  template<typename A, typename B, typename...Rest><br>  using Type = F<B, A, Rest...>;<br>};<br><br>template<template<typename...> typename F, typename...Args><br>struct PartialApply {<br>  template<typename...Rest><br>  using Type = F<Args..., Rest...>;<br>};<br><br>using X = typename PartialApply<Flip<S>::Type, int>::template Type<bool>; // there should be S<bool, int></span><br><br>Now this can be compiled only by icc. Other compilers become mad and start to report very strange error. For example, gcc says that there is "pack expansion of 'B'" in Flip. clang and msvc produce similar error. Is this code valid C++ after all?<br></div></blockquote><div><br></div><div>Well, same as above: the template `Flip<S>::Type` is invalid and thus causes the <i>entire program</i> to be ill-formed, no diagnostic required.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div>Also if write similar code but in context of lambdas all compilers will work as expected. Does processing of variadic lambdas differ from processing of variadic templates?</div></blockquote><div><br></div><div>You'd have to show an example.</div><div><br></div><div>For more on the wacky Wild West situation around interchangeability of pack and non-pack template parameters, see the later sections of</div><div><a href="https://quuxplusone.github.io/blog/2019/01/20/covariance-and-contravariance/">https://quuxplusone.github.io/blog/2019/01/20/covariance-and-contravariance/</a></div><div><br></div><div>–Arthur</div></div></div></div></div></div></div>