gcc not_fn implementation:为什么_Not_fn接受额外的int参数?

Edg*_*jān 4 c++ gcc libstdc++ c++17

最近我看了一下gcc 提供的函数模板的实现.std::not_fn

此函数模板的返回类型是_Not_fn- 包装类模板,它取消包装的可调用对象.

事实证明,_Not_fn构造函数接受一个int未明确使用的附加参数:

template<typename _Fn2>
    _Not_fn(_Fn2&& __fn, int)
    : _M_fn(std::forward<_Fn2>(__fn)) { }
Run Code Online (Sandbox Code Playgroud)

对构造函数的调用如下所示:

template<typename _Fn>
inline auto not_fn(_Fn&& __fn) 
    noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value)
{
    return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0}; // <- 0 is passed here
}
Run Code Online (Sandbox Code Playgroud)

题:

这个附加int参数的目的是什么?为什么gcc实现需要它?

Pra*_*ian 8

添加了伪参数,因为实现者不希望完美的转发构造函数比非参数的复制构造函数更好const.

考虑这个例子

struct _Not_fn
{
    template<typename _Fn2>
    _Not_fn(_Fn2&&)
    { /* */ }

    _Not_fn(const _Not_fn&)
    { /* */ }
};

_Not_fn f([]{});
_Not_fn f1(f);         // calls perfect forwarding constructor
_Not_fn f2(const_cast<const _Not_fn&>(f));    // calls copy constructor
Run Code Online (Sandbox Code Playgroud)

移动构造函数也存在同样的问题.虚拟int参数的引入解决了这个问题.

实例

变化被引入到修复的bug 70564.

  • 这是提交:https://github.com/gcc-mirror/gcc/commit/f3bc5fecf2cb6f298d12c30cf15306f843bcdce4 (3认同)