This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Patch for constexpr variable templates


On 2014-07-28 13:09, Andrew Sutton wrote:
 3)  auto (*f (auto)) (auto); // generic function 'f' constrained to
returning a unary function pointer deduced from the return expression.

Really? I've read the comment and I'm still not sure how to read this
declaration.

The first and last 'auto' in the line would be resolved by return type deduction, the second, in the parameter list, would be a synthesized template argument.

E.g. If the function were defined as

  auto (*crazy (auto f)) (auto)
  {
    return f;
  }

then it is only well formed if instantiated with an 'f' that is convertible to some ptr-to-function type of the form "R (*) (A)". At which point return type deduction would subst 'R' for the first 'auto' and 'A' for the last.

If it were passed a pointer to the following function

  int F(float);

then it should be instantiated as

  int (*crazy (int (*f) (float))) (float)
  {
    return f;
  }

My point with case (3) is that it contains two function parameter lists that contain 'auto' but they need to be dealt with differently for generic function template argument synthesis and for return type deduction.

Ultimately, the last two would require the generalized 'auto'
type deduction behavior.  The difficulty is that there doesn't
appear to be any existing means for determining, at parse time
of the first "(auto", whether we're forming a function or
variable declaration.  Maybe such state would fall out of a
generalized 'auto' solution.

I was wondering about this on the drive to work this morning. Maybe
trying to pin down semantics at parse time isn't the right approach.

I have a feeling you may be right.

That is, always parse declarations like variables, and then build up
template parameters as needed during grorkdecl or grokfndecl. Or maybe
that's too late. I don't know.

My thinking was going the other way other initially (assuming a function until you know it isn't). But I think deduced return types would cause problems with this so I'm thinking the "assume variable" route might be better. We'd have to generate some form of parametric type tree for the variable type before deduction from the initializer anyway and it may be that such a tree could be transformed into the function type should the decl turn out to be a function.

I recall my initial experience of implementing generic functions: I tried to work in the grok*decl space, but found that so many cases had to be handled explicitly and types rebuilt afterwards potentially after errors about 'auto' had already been issued (which needed additional cases to avoid). I remember it being nasty. But it was my first hack on the GCC code base; so that was probably a factor (still is!). Switching to the parsing route allowed to transform the code on the fly as if it had been written with the full template header from the start; making all the existing code happy. I would like to eliminate the possibility of making the "during parsing" route work before diving back in to a post-parse solution.

Whatever the solution for auto, it will be the same for concepts.
We'll just add constraints to the auto-type whenever we find a
constrained-type-specifier.

Agreed.

Adam


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]