为什么声明' void(*pf)(int) = bar; '会触发下面代码片段中的' static_assert
Why does the declaration `void(*pf)(int) = bar;` fires the `static_assert` in the snippet below?
这是我之前问题的延续。注意,声明void (*pf)(int) = bar;
触发static_assert
。我不明白为什么。还请注意,如果我在此声明中将bar
替换为bar<const int>
,则代码将编译。
#include <iostream>
#include <type_traits>
template<typename T>
void bar(T t)
{
static_assert(std::is_same<T, const int>::value, "Error!");
std::cout << t << 'n';
}
int main()
{
// static_assert doesn't fire because T==const int
bar<const int>(1);
// But here static_assert fires because T==int (see the error message). Why is this?
// If I replace `bar` by `bar<const int>` below the code compiles.
void(*pf)(int) = bar;
pf(1000);
}
生活例子
行为非常简单。从下面的函数指针类型推导出T
为int
,因此static_assert
失败。
void(*pf)(int) = bar; // [T = int]
如果我将
bar
替换为bar<const int>
,代码将编译
这是因为你现在已经明确地指定T
是const int
,而不再被推断为int
。
void(*pf)(int) = bar<const int>; // [T = const int]
你仍然可以创建一个类型为void(*)(int)
的函数指针,指向函数void(const int)
,因为顶级const
不是函数签名的一部分。
将const
添加到函数指针类型中没有帮助,因为同样的原因,在推导出T
之前,函数参数类型中的顶级const
被丢弃,并且导致与第一个示例相同的行为。
void(*pf)(const int) = bar; // [T = int]
编译器根据提供的函数指针签名推断出T
= int
。将void(*pf)(int)
更改为void(*pf)(const int)
并不能解决这个问题,因为cv限定符在类型推导期间被删除(并且,正如dyp在注释中指出的那样,在确定函数的类型时)。§14.8.2.1/3的c++ 11草案("从函数调用中推导模板实参"):
如果p是cv限定类型,则p类型的顶级cv限定符类型推导时忽略
要解决这个问题,显式地指出您想要的类型:
void(*pf)(const int) = bar<const int>;
相关文章:
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 这两个代码片段相似,但显示的结果不同
- 如何替换此示例代码片段中已弃用的handler_type_t或 boost::asio::handler_type?
- 如果我在下面的代码片段中添加"delete[] d;",为什么我得到零?
- 我遇到了这个代码片段,不明白. 它递归检查 C++ 字符串中是否存在大写字符
- 任何人都可以解释一下我是否需要 & 在第一个代码片段中
- 提取狮身人面像文档中的C++代码片段
- 为什么此代码片段有效?如何取消引用空点?
- 无法在这个基本的Qt代码片段中找到错误,但我被告知它肯定存在?
- 这个代码片段中会发生死锁吗?为什么
- 这个代码片段中的while循环是如何工作的
- 在给定的代码中,有人可以解释一下(int i = 0; i<len; i++)count[str[i]]++的代码片段;
- 为什么我的C++代码在以下打印链表的代码片段中显示分段错误?
- 为什么这两个代码片段具有相同的效果?
- 以下代码片段的时间复杂度是多少?
- 为什么以下代码片段存在编译错误
- 如何在此代码片段中创建 begin() 指针
- 为什么这个简短的模板代码片段有效
- 为什么这个代码片段在 C 和 C++ 中生成完全不同的汇编代码?
- 我应该修复这个晦涩而优雅的C 代码片段吗?