On 2013-10-09 4:37, Jason Merrill wrote:
On 10/07/2013 05:14 AM, Adam Butcher wrote:
+                 /* Forbid ambiguous implicit pack expansions by only allowing
+                    a single generic type in such a parameter.

+                    XXX: Maybe allow if explicitly specified template
+                    XXX: 'typename...' account for all expansions?  Though this
+                    XXX: could be tricky or slow.

This seems wrong.  The standard says,

The invented type template-parameter is a parameter pack if the corresponding parameter-declaration de-
clares a function parameter pack (8.3.5).

So if we have a function parameter pack, any generic type parameters
in the type are packs.

Of course; makes sense. I had confused myself. Not that it's a function parameter pack, but presumably you would expect

  auto f(tuple<auto...> p)

to be supported? This doesn't work with my existing impl since I only generate a variadic type on the declaration of a function parameter pack.

I think the following cases should also work

  auto g1(std::tuple<std::shared_ptr<auto>, std::tuple<auto...>> p)
auto g2(std::tuple<std::shared_ptr<auto>, std::tuple<std::shared_ptr<auto>...>> p)

In both cases, the first generic type is a plain type and the second is a type pack.

Making the parameter a function parameter pack should also work

  auto h1(std::tuple<std::shared_ptr<auto>, std::tuple<auto...>>... v)
auto h2(std::tuple<std::shared_ptr<auto>, std::tuple<std::shared_ptr<auto>...>>... v)

The first 'auto' is a pack expanded by 'v' and the second is expanded within the second tuple (and required to be consistent among all 'v' arguments).

+ /* If there is only one generic type in the parameter, tentatively + assume that that it is a parameter pack. If it turns out, after
+            grokdeclarator, that the parameter does not contain a pack
+            expansion, then reset it be a non-pack type.  */
+         if (cp_num_implicit_template_type_parms == 1)
+           TEMPLATE_PARM_PARAMETER_PACK
+             (TEMPLATE_TYPE_PARM_INDEX
+               (cp_last_implicit_template_type_parm)) = true;

This will cause problems with type comparison, since TYPE_CANONICAL
of the implicit parm doesn't have TEMPLATE_PARM_PARAMETER_PACK set.

Indeed it does.

That's why I was talking about using tsubst to replace a non-pack with
a pack.

Will do.

+       parser->implicit_template_scope = class_scope;
+      else
+       parser->implicit_template_scope = fn_parms_scope;
+ current_binding_level = parser->implicit_template_scope->level_chain;

Why not make implicit_template_scope the actual template scope,
rather than the function/class?  It looks like all the users
immediately take the level_chain.

My original intent was to store the actual template parm scope but I changed it to the containing scope to make the comparison in cp_parser_parameter_declaration_list; It determines the completion point of the implicit template scope. It is terminated once current_binding_level returns to the initiating scope. I'll have another look to reduce level_chain traversal.

+/* Nonzero if parsing a context where 'auto' in a parameter list should not + trigger an implicit template parameter. Specifically, 'auto' should not + introduce a new template type parameter in explicit specializations, trailing
+   return types or exception specifiers.  */
+int cp_disable_auto_as_implicit_function_template_parm;

Can we put this in cp_parser, invert the sense of the flag, and only
set it during cp_parser_parameter_declaration_clause?

Done. But it still needs a flag to disable in the case of explicit template specialization. At the moment I've replaced the explicit_specialization_p parm of cp_parser_single_declaration with a global cp_parsing_explicit_function_specialization but not sure if that's the best solution.

I'll post an update once I get some time to rework the pack stuff.

Cheers,
Adam

Reply via email to