By the text of the standard, it would suggest that you have a point. But the syntax did not make it easy for the compiler vendors.


From: Std-Discussion <std-discussion-bounces@lists.isocpp.org> on behalf of SD SH via Std-Discussion <std-discussion@lists.isocpp.org>
Sent: Sunday, 12 July 2026 08:50:56
To: Deslauriers, Douglas via Std-Discussion <std-discussion@lists.isocpp.org>
Cc: SD SH <Z5515zwy@outlook.com>
Subject: [std-discussion] a doubt about getting the pointer of a function name with function templates
 
Hi.

1. Intro

```
template<typename...>
void foo() { }

auto _ = &foo; // is it OK?
```

GCC, Clang and MSVC have different results of it:
      GCC: [success]
      Clang: error: variable '_' with type 'auto' has incompatible initializer of type '<overloaded function type>'
      MSVC: error C3535: cannot deduce type for 'auto' from 'overloaded-function'

2. My Opinion

The type of `_` is `decltype(&foo)` [a],
`&foo` can be deduced as `&foo<>` here [b], and have a unique function.
So `&foo` should be deduced as `void foo<>(void)` [c], then `decltype(&foo)` is `void(*)(void)`.
Therefore, the code is expected to be:
      ```
      template<typename...>
      void foo(void) { }
      template<>
      void foo<>(void) { } // implicit specialization by `foo`

      void(*_)(void) = static_cast<void(*)(void)>(&foo<>);
      ```

By the text of Standard, seems it is well-formed, or I made some mistakes on it.
The compilers didn't have the same behaviors. Is the code correct?

3. Compilers Have Different Behaviors of Same Expressions
The 3 compilers all accepted these code:
```
template<typename...>
int foo(void) { return 0; }

auto _ = (&foo)();
```
It shows that all the compilers can accept `&foo` as `&foo<>`.
If it is true, both Clang and MSVC has different behaviors of the expression `&foo`.

While the 3 compilers all rejected these code:
```
template<typename...>
int foo(void) { return 0; }

using X = decltype(&foo);
```
So, GCC also has different behaviors of the expression `&foo`.

Overall, all of GCC, MSVC and Clang has different behaviors of the expression `&foo`.
I doubt the all these compilers didn't follow the Standard, or the Standard itself have ambiguities in some places.

4. References:

[a] [dcl.type.auto.deduct]-p1
      Placeholder type deduction is the process by which a type containing a placeholder type is replaced by a deduced type.
[b] [temp.arg.explicit]-p4
      Trailing template arguments that can be deduced ([temp.deduct]) or obtained from default template-arguments may be omitted from the list of explicit template-arguments.
      [Note 1: A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments. — end note]
      If all of the template arguments can be deduced or obtained from default template-arguments, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.
[c] [expr.prim.id.general]-p6
      For an id-expression that denotes an overload set, overload resolution is performed to select a unique function ([over.match], [over.over]).
[d] [over.over]-p1
      ... [Note 1: Any redundant set of parentheses surrounding the function name is ignored ([expr.prim.paren]). — end note]
[e] CWG 2848. Omitting an empty template argument list for explicit instantiation

5. Others
The text of the Standard is cited from https://eel.is/c++draft/ .
All the compiler behaviors of code above are given by Godbolt.
      GCC: x86-64 gcc 16.1 with command `-std=c++23`
      Clang: x86-65 clang 22.1.0 with command `-std=c++23`
      MSVC: x64 msvc v19.51 VS18.6 with command `/std:c++latest`