提问人:Battler 提问时间:10/2/2023 最后编辑:Battler 更新时间:10/2/2023 访问量:116
使用常量值模板参数创建模板函数别名时出现问题
Problem creating template function alias with const value template arguments
问:
这是不编译的代码的简单版本。我知道存在的常量值和值签名函数都是模棱两可的,但我需要两个基于值模板参数恒常性的不同函数。但我没想到在取 f1 的别名时会遇到问题。它适用于所有 const 类型引用,但不适用于 const 值。
template<class... ARGS_T>
void f1(ARGS_T...) {
std::cout << (std::is_const_v<ARGS_T> || ...) << std::endl;
}
template<class... ARGS_T>
constexpr void(*f2)(ARGS_T...) = f1<ARGS_T...>;
class C {};
int main() {
f1<const int, const C>(1, C());
(*f2<const int, const C>)(3, C());
return 0;
}
两个版本的 f1 都毫无问题地实例化并且具有不同的地址,为什么我不能以这种方式创建两个不同的指针?
我在 Windows 上使用 g++(Rev10,由 MSYS2 项目构建)12.2.0
编译错误:
C:/Alias/main.cpp: In instantiation of 'constexpr void (* const f2)(int, C)<const int, const C>':
C:/Alias/main.cpp:15:8: required from here
C:/Alias/main.cpp:9:17: error: no matches converting function 'f1' to type 'void (* const)(int, class C)'
9 | constexpr void(*f2)(ARGS_T...) = f1<ARGS_T...>;
| ^~
C:/Alias/main.cpp:4:6: note: candidate is: 'template<class ... ARGS_T> void f1(ARGS_T ...)'
4 | void f1(ARGS_T...) {
| ^~
答:
2赞
Jan Schultke
10/2/2023
#1
这看起来像是 GCC 中的编译器错误,与函数参数有关。首先,请注意,函数参数不是函数类型的一部分:const
const
生成参数类型列表后,在形成函数类型时,将删除任何修改参数类型的顶级 cv 限定符。
这意味着 和 是同一类型。这同样适用于函数指针类型和 。所有主要编译器都接受以下代码,因为它们应该接受:void(int)
void(const int)
void(*)(int)
void(*)(const int)
void fi(int);
void fci(const int);
void(*pfi)(int) = &fi; // OK
void(*pfci)(int) = &fci; // OK
void(*pcfi)(const int) = &fi; // OK
void(*pcfci)(const int) = &fci; // OK
出于某种原因,GCC 在处理可变参数模板化函数类型时无法正确执行此类型调整:
// note: using a single T instead of ARGS_T... works
template<class... ARGS_T>
void f(ARGS_T...) {}
void(*pfi)(int) = &f<int>; // OK
void(*pfci)(int) = &f<const int>; // error
void(*pcfi)(const int) = &f<int>; // OK
void(*pcfci)(const int) = &f<const int>; // error
请参阅编译器资源管理器。
Clang 和 MSVC 编译此代码,但 GCC 不编译。的类型与 的类型相同,因此此代码应进行编译,就像第一个示例一样。f<const int>
void(const int)
void(int)
注意:我已经提交了 GCC 错误报告。请参阅 GCC Bug 111662。
评论