首页 > 解决方案 > C++ 函数到指针隐式转换:哪个编译器是正确的?Clang 和 GCC 不同意

问题描述

template <typename Type, Type Func>
struct A
{
};

void func();

A<void(), func> a; // same result with A<void(), &func> a;

此代码使用 Clang(包括最新的 8.0.0)编译,但不能使用 GCC(包括最新的 9.1)编译。

海湾合作委员会 说:error: 'void()' is not a valid type for a template non-type parameter

哪个编译器是正确的,为什么?

更新

我猜 GCC 是错误的,因为在 Clang 和 GCC 上都编译了以下代码:

template <void()>
struct A
{
};

void func();

A<func> a; // same result with A<&func> a;

因此,与 GCC 在第一个示例中报告的相反,void()似乎是“模板非类型参数的有效类型”

标签: c++gccclang

解决方案


与函数参数类型发生的情况类似,如果非类型模板参数的类型是函数类型,则将其调整为指向函数类型[temp.param]/8的指针:

将类型为“T 数组”或函数类型 T 的非类型模板参数调整为“指向 T 的指针”类型。

所以clang是对的。GCC 错误报告已经存在错误 #82773


只有当前的 c++ 标准工作草案承认将模板参数替换为以下模板参数的过程。因此可以说该标准并不明确,因为它没有指定在每次替换后执行类型调整。


推荐阅读