4

I'm writing a deduction guide in the style of an abbreviated function template, but I'm not sure if it's allowed. It compiles on gcc and clang, but not msvc.

The error is:

error C3539: a template-argument cannot be a type that contains 'auto'

Which compiler is doing the right thing?

try it out here

template <typename Type, int Count>
struct Array
{
    Type data[Count];

    Array (auto ... arg)
    {
        int count = 0;
        ((data[count++] = arg),...);
    }
};

// abbreviated function template syntax - fails in msvc
Array (auto first, auto ... next) -> Array<decltype(first), 1 + sizeof...(next)>;

// regular syntax
// template <typename Type, typename ... Args> Array (Type first, Args ... next) -> Array<Type, 1 + sizeof...(Args)>;

int main ()
{
    Array a(1,2,3);
}
max66
  • 65,235
  • 10
  • 71
  • 111
Petwoip
  • 1,365
  • 2
  • 17
  • 25
  • It is pretty clear from [MSDN documentation](https://learn.microsoft.com/en-us/cpp/cpp/auto-cpp?view=msvc-170#restrictions-and-error-messages) that msvc does not allow `auto` in parameters and template arguments in the default [`/Zc:auto`](https://learn.microsoft.com/en-us/cpp/build/reference/zc-auto-deduce-variable-type?view=msvc-170) mode. See [C3533](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c3533?view=msvc-170) and [C3539](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c3539?view=msvc-170) – Remy Lebeau Dec 14 '22 at 19:27

1 Answers1

4

According to [dcl.spec.auto.general]/6 any use of a placeholder type (e.g. auto) that is not explicitly permitted in [dcl.spec.auto] is not permitted.

And I don't see anything applying to deduction guides mentioned there. In particular [dcl.spec.auto.general]/2 which allows it in function parameters is explicitly limited to parameter-declarations in function declarations and lambda expressions.

So it does seem ill-formed to me.

However, I don't see any reason for this. I suspect that [dcl.spec.auto] and the definition of abbreviated function template in [dcl.fct] should just be extended to include parameter lists of deduction guides with analogues rules to match the statement in [temp.deduct.guide] that the parameter list of a deduction guide follows the same restrictions as that of a function declaration.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • 1
    Why would they want to encourage people to use this in places where you're *definitely* going to have to have a bunch of `decltype(variable_name)` instead of just using `template`? Broadly speaking, outside of lambdas, if you ever reach for `decltype` for an `auto` function parameter, you should stop and write a template header. – Nicol Bolas Dec 14 '22 at 21:08
  • 1
    @NicolBolas I don't really think that is a good reason to add a non-obvious syntax difference to function/constructor declarations, when deduction guides mimic them. But even so in e.g. OP's example `template Array(F first, auto ... next) -> Array;` wouldn't need a type name or `decltype` on `next` if the use of the placeholder was allowed. (Of course you may consider mixing the styles even worse, but there should be examples where no type name is used.) – user17732522 Dec 14 '22 at 21:22