此问题假设您熟悉P1895R0 中tag_invoke引入的定制点管理技术。
自定义点对象可以根据 P1895R0 定义为:
inline constexpr struct foo_cpo {
// simplified original by omitting noexcept forward and using auto arg
auto operator()(auto const &x) -> decltype( std::tag_invoke(*this, x) ) {
return std::tag_invoke(*this, x); // <--^-- here are the Niebloid
}
} foo;
Run Code Online (Sandbox Code Playgroud)
但是鉴于这种技术的关键是直接处理对象,并将任何和所有 ADL 委托给一个且唯一商定的 identifier tag_invoke,那么似乎可以通过简单的方式实现相同的效果,
inline constexpr struct {
auto operator()(auto const &x) -> decltype( tag_invoke(*this, x) ) {
return tag_invoke(*this, x); // no Niebloid. directly ADL call tag_invoke
}
} foo;
Run Code Online (Sandbox Code Playgroud)
例如,P1895R0 中的类型擦除示例https://godbolt.org/z/3TvO4f可以在不使用 Niebloid 的情况下重新实现:https ://godbolt.org/z/dzqE7b 。代码与原始逐字相同,对 Niebloid 的定义取模,std::tag_invoke并对所有自定义点对象使用上述 ADL 形式。
尼布洛德的存在真正满足什么要求tag_invoke?
我不认为它tag_invoke本身是一个函数对象是绝对必要的。但是如果我们认为有必要,将它定义为一个对象给了我们一个方便的地方来放置毒丸过载。将函数作为可以传递给高阶函数的一等公民通常很好。就是这样,真的。