<div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">06.04.2019, 19:36, "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>:</div><blockquote xmlns="http://www.w3.org/1999/xhtml" type="cite"><div><div><div><div><div><div>On Fri, Apr 5, 2019 at 7:46 PM Alexander Us via cfe-dev <<a rel="noopener noreferrer" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:</div><div><blockquote 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.</div></blockquote><div> </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 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?</div></blockquote><div> </div><div>My understanding is that all four compilers' behavior is correct. Template `U` is well-formed <strong><em>only </em></strong>when Rest... is an empty pack, and thus the program is ill-formed (no diagnostic required) via <a rel="noopener noreferrer" 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> </div><blockquote 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?</div></blockquote><div> </div><div>Well, same as above: the template `Flip<S>::Type` is invalid and thus causes the <em>entire program</em> to be ill-formed, no diagnostic required.</div></div></div></div></div></div></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">Okay, it really seems that Flip is ill-formed. But changing Flip in the second example to:<br /><br /><span style="font-family:andale mono,times;">template<template<typename, typename> typename F><br />struct Flip {<br />  template<typename A, typename B><br />  using Type = F<B, A>;<br />};</span><br /><br />actually doesn't fix compilers. They're still saying that the program is incorrect because of this mystical pack expansion of 'B'. I assume that now it is a bug.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><blockquote xmlns="http://www.w3.org/1999/xhtml" type="cite"><div><div><div><div><div><div><div> </div><blockquote 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> </div><div>You'd have to show an example.</div></div></div></div></div></div></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">Code with lambda functions:<br /><br /><span style="font-family:andale mono,times;">auto fvar = [](auto f) {<br />  return [f](auto a, auto...rest) { return f(a, rest...); };<br />};<br /><br />auto sqr = [](auto a) { return a * a; };</span><br /> </div><div xmlns="http://www.w3.org/1999/xhtml"><span style="font-family:andale mono,times;">auto foo() {<br />  return fvar(sqr)(2); // works fine<br />}</span><br /><br />This case looks similar to templates and now it seems that it is ill-formed too. Translating second case to lambdas and adding flip2 to avoid probable ill-formedness also make compilers work correct:</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"><span style="font-family:andale mono,times;">auto shift = [](auto a, auto b) { return a << b; };</span></div><div xmlns="http://www.w3.org/1999/xhtml"><br /><span style="font-family:andale mono,times;">auto flip2 = [](auto f) {<br />  return [f](auto a, auto b) { return f(b, a); };<br />};<br /><br />auto partialApply = [](auto f, auto...args) {<br />  return [f, args...](auto...rest) { return f(args..., rest...); };<br />};<br /><br />auto bar() {<br />  return partialApply(flip2(shift), 3)(1); // works fine<br />}</span></div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">That is this difference in processing of code I asked about.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">---</div><div xmlns="http://www.w3.org/1999/xhtml">Alexander</div><div xmlns="http://www.w3.org/1999/xhtml"> </div>