为什么声明`void(*pf)(int)= bar;`在下面的代码片段中触发`static_assert`?

Mao*_*Mao 3 c++ templates c++11

这是我先前问题的延续.请注意,声明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);
}
Run Code Online (Sandbox Code Playgroud)

实例

Pra*_*ian 5

这种行为非常简单.从下面的函数指针类型T推断出int,因此static_assert失败.

void(*pf)(int) = bar; // [T = int]
Run Code Online (Sandbox Code Playgroud)

如果我在此声明中替换bar,bar<const int>则代码编译

那是因为你现在已经明确指定了Tconst int,它的不再推导出int.

void(*pf)(int) = bar<const int>; // [T = const int]
Run Code Online (Sandbox Code Playgroud)

你仍然可以创建类型的函数指针void(*)(int)的函数void(const int),因为顶层consts为不是函数签名的一部分.

添加const到函数指针类型没有帮助,因为相同的原因,const函数参数类型中的顶级在T推断之前被丢弃,并且它导致与第一个示例相同的行为.

void(*pf)(const int) = bar;  // [T = int]
Run Code Online (Sandbox Code Playgroud)