GCC中std::not_fn实现疑问:_Not_fn为何接受额外int参数?
解析GCC中std::not_fn的_Not_fn构造函数里的额外int参数
最近我研究GCC实现的std::not_fn函数模板时,发现它返回的_Not_fn包装类模板里藏着个有点反直觉的构造函数——带了一个看起来完全没被用到的int参数,咱们来唠唠这个设计到底是干嘛的。
先看一下这个构造函数的代码:
template<typename _Fn2> _Not_fn(_Fn2&& __fn, int) : _M_fn(std::forward<_Fn2>(__fn)) { }
核心作用:解决重载决议的歧义
这个int参数本质是个重载标记,用来避免构造函数之间的歧义问题。
咱们想一下,如果没有这个额外参数,当我们尝试用一个已经是_Not_fn类型的对象去构造新的_Not_fn实例时,编译器会面临两个候选构造函数:
- 类默认生成的拷贝/移动构造函数(匹配
_Not_fn类型参数) - 上面的模板构造函数(因为它能接受任意类型,自然也能匹配
_Not_fn)
这时候编译器就会陷入重载决议的歧义,不知道该选哪个。
而加上这个int参数后,情况就不一样了:
- 这个构造函数只能被那些显式传入一个
int值的调用触发(在std::not_fn的内部实现里,调用它时会传一个比如0的常量) - 普通的拷贝/移动操作(比如直接赋值、传参)不会触发这个构造函数,因为不会额外传
int参数
这样就完美区分了“从外部可调用对象构造_Not_fn”和“从_Not_fn自身实例拷贝/移动构造”这两种场景,让重载决议完全按预期工作。
为什么参数没被使用?
因为它仅仅是个标记符号,作用只在重载决议阶段——用来让编译器识别出这是一个特定的构造路径,不需要在构造逻辑里用到它的具体值,所以也就没必要在函数体内引用它。
简单说,这个看似多余的int参数是GCC实现里一个巧妙的小技巧,专门用来绕过重载歧义的坑,保证std::not_fn的包装逻辑能稳定运行。
内容的提问来源于stack exchange,提问作者Edgar Rokjān
相关产品推荐
相关产品推荐

