auto占位符能否推导非类型模板参数的函数结果?代码合规性解析
Let's break down your questions one by one, since they touch on some subtle details of C++17's auto non-type template parameters.
Is your first code compliant with C++17?
Absolutely. C++17 added support for auto as a placeholder in non-type template parameters, which lets the compiler infer the parameter's type from the argument you pass. In this case:
template <auto(*X)()> struct Foo { decltype(X()) x; }; int bar(); int main() { static_cast<void>(Foo<bar>{}); }
The compiler looks at bar, sees it's a pointer to a function with no arguments returning int, and deduces that auto in auto(*X)() resolves to int. Both GCC and Clang accept this because it's exactly how the feature is designed to work.
Why does GCC reject the second snippet?
This is a quirk (read: bug) in GCC's implementation, not a problem with your code. Let's look at the problematic code again:
template <class T, auto(*X)(T)> struct Foo { decltype(X(0)) x; }; int bar(int); int main() { static_cast<void>(Foo<int, bar>{}); }
When you explicitly set T to int, the type of X should be auto(*)(int). Since bar is a function of type int(*)(int), this is a perfect match—there's no deduction needed for T anymore, and the compiler should just infer that auto in auto(*X)(T) is int (matching bar's return type).
Clang handles this correctly, as it follows the standard's intent: once T is explicitly specified, the remaining auto placeholder can be resolved using the provided function pointer. GCC's error message ("unable to deduce 'auto (*)(T)' from 'bar'") is incorrect here because T isn't unknown—it's given as int, so all necessary information is available.
If you need a workaround for GCC, you can replace auto with the explicit return type (though this loses the flexibility of auto):
template <class T, int(*X)(T)> struct Foo { decltype(X(0)) x; };
But rest assured, your original code is valid C++17, and the GCC error is a compiler-specific issue that doesn't reflect the standard's rules.
内容的提问来源于stack exchange,提问作者W.F.

