9

Consider simple example:

template <auto(*X)()>
struct Foo {
    decltype(X()) x;
};

int bar();

int main() {
    static_cast<void>(Foo<bar>{});
}

Both [gcc] and [clang] seem to accept the code. Is the code really c++17 compliant? If so is there some other rule that makes the following code ill formed?

template <class T, auto(*X)(T)>
struct Foo {
    decltype(X(0)) x;
};

int bar(int);

int main() {
    static_cast<void>(Foo<int, bar>{});
}

This one makes only [gcc] unhappy.

Error message:

prog.cc: In function 'int main()':
prog.cc:9:35: error: unable to deduce 'auto (*)(T)' from 'bar'
     static_cast<void>(Foo<int, bar>{});
                                   ^
prog.cc:9:35: note:   mismatched types 'T' and 'int'
W.F.
  • 13,888
  • 2
  • 34
  • 81

1 Answers1

3

Yes, auto may be used inside a compound type ([temp.param]/4.6, [dcl.type.auto.deduct]). I believe that gcc is in error in your second example: your explicitly specified T of int is substituted before performing deduction ([temp.deduct]/2.3, /5, and /6, referenced by [dcl.type.auto.deduct]/2.3 and /4).

W.F.
  • 13,888
  • 2
  • 34
  • 81
Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Where does the standard guarantee that the substituting is performed before the deducing? – xskxzr Jan 28 '18 at 04:11
  • @xskxzr: Added. gcc/clang even support `template void f(T(&)[N]);` although they disagree about the resulting type of `N`. I have a harder time seeing that in the wording, since it requires deducing `N` and _then_ its type. – Davis Herring Jan 28 '18 at 06:34