这是简化版本的代码,不编译。我知道const value和value signature函数都是不明确的,但我需要两个不同的函数,基于值模板参数的constness。但我没想到会有问题采取一些别名的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,Built by MSYS2 project)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...) {
| ^~
1条答案
按热度按时间mjqavswn1#
这看起来是GCC中的编译器错误,与函数参数中的
const
有关。首先,注意函数参数中的const
不是函数类型的一部分:在生成参数类型列表之后,任何修改参数类型的顶级 * cv-限定符 * 在形成函数类型时被删除。
这意味着
void(int)
和void(const int)
是相同的类型。这同样适用于函数指针类型void(*)(int)
和void(*)(const int)
。所有主要的编译器都接受以下代码,因为它们应该这样做:由于某些原因,GCC在处理可变模板函数类型时不能正确执行这种类型调整:
Clang和MSVC可以编译这些代码,但GCC不能。
f<const int>
的类型是void(const int)
,它与void(int)
的类型相同,所以这段代码应该可以编译,就像第一个例子一样。