MSVC拒绝编译这段代码,这样做正确吗?

4

看一下这段代码(godbolt):

#include <type_traits>
#include <memory>
#include <cstdlib>

using namespace std;

template<auto L, class T = decltype(L)>
using constant = integral_constant<T, L>;

int main() 
{
    unique_ptr<void, constant<&free>> p1;
    unique_ptr<void, constant<free>> p2;    // <-- MSVC refuses to compile this line
    return 0;
}

为什么 MSVC 拒绝编译这个高亮行?这段代码有效吗?

MSVC 的输出结果是:

<source>(13): error C2975: 'L': invalid template argument for 'constant', expected compile-time constant expression
<source>(7): note: see declaration of 'L'

3
它只是说“我拒绝”吗? - jarmod
@jarmod 我的错。已修复... - C.M.
3
::freestd::free 可以编译通过,因此某些编译器可能会用编译器内置函数替换 free 函数。 - Artyer
3
移除using namespace std;并相应地在unique_ptr前加上std::限定符也可以使程序编译通过。free可能只是别名C库版本,它具有C语言链接,但这对于auto非类型模板参数来说不重要(但尝试将具有语言链接的函数指针分配给C ++语言链接的函数地址时会产生问题,也许这会导致此处的明显错误行为)。 - dfrib
为什么“using namespace std;”被认为是不良实践? - phuclv
1个回答

3

在C++20之前,这看起来像是MSVC的一个bug。

在C++20之后,行为是未指定的(感谢@heapunderrun),因为free不在你被允许取地址的函数列表中。但我认为这仍然是一个bug(即使符合标准),因为如果使用&,MSVC会让你获取同一函数的地址。


在这种情况下的模板参数推导就像通过constexpr auto x = free;(参见[temp.arg.nontype]/1)那样进行,并且MSVC接受上述声明,推导出一个函数指针。

传递模板参数时禁止某些隐式转换,允许的转换在[expr.const]/10中列出,包括“从函数到指针”的转换。


有没有想法为什么 ::free 在 MSVC 上可以工作,而 free 却不行? - C.M.
1
@C.M. 可能是这个 https://dev59.com/5VMI5IYBdhLWcg3wpdK7,因为 using namespace std; 使得 freestd::free - Richard Critten
5
在考虑到std::free不在指定的可寻址函数之列时,这种从函数到指针的转换是否仍然保证成功? - heap underrun
所以,在 C++20 中,他们让那些需要 free 或其他操作的自动释放对象更难创建了...哎... - C.M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接