问题描述
在下面的代码中,命名空间 S
中的独立组件有自己的 Big
和 Small
类型定义,以及一个 split
函数来拆分一个 { {1}} 到 Big
的集合中。
Small
还提供了另一个函数 S
,它利用了 work
,并且旨在由 split
本身以及其他依赖组件使用,例如命名空间 S
中的一个,假定它们提供自己对 D
和 Big
的定义以及自己对 Small
的定义,这些定义将通过 ADL 进行标识。¹
split
嗯,实际上 #include <iostream>
#include <string>
#include <utility>
#include <vector>
namespace S /* standalone */ {
struct Big{};
struct Small{};
std::vector<Small> split(Big b) {
std::cout << "S" << std::endl;
return {/* use b to make output */};
}
template<typename BigT>
void work(BigT/* acutally this is a template class with `BigT` as a template paramter*/ x) {
split(x); // correspondingly `split` is not applied on `x` but on the `BigT` which is part of it
// a lot of complex stuff
}
}
namespace D /* dependent on standalone */ {
struct Big{};
struct Small{};
std::vector<Small> split(Big b) {
std::cout << "D" << std::endl;
return {/* use b to make output */};
}
}
int main() {
S::Big line1{};
D::Big line2{};
S::work(line1); // uses S::split
S::work(line2); // uses D::split
}
是一个函数对象,而不是一个函数²,
S::split
所以 ADL 不起作用。
对于如何满足这些需求有什么建议吗?
从评论中可以看出,Niebloids 和/或 namespace S {
struct Split {
std::vector<Small> operator()(Big) const {
std::cout << "S" << std::endl;
return {};
}
} split;
}
可能代表了我的问题的答案。我真的很想更多地了解这些概念。
就目前而言,我对 Niebloids 的理解(我正在阅读 this blog from Eric Niebler)是它们是(当它们在范围内时)阻止 ADL 的函数对象,因此将所有函数调用“集中”到不合格的与 niebloid 同名的自由函数;然而,他们的 tag_invoke
依赖 ADL 将调用转发到适当的free 函数。因此,在我的示例代码中,operator()
是一个函数对象和 S::split
是一个自由函数之间的对比似乎无法由 niebloids 解决,除非我使 D::split
成为一个自由函数(其中case ADL 在我的简单场景中就足够了)。
¹ 最初在 S::split
和 work
中都定义了 S
,上面的代码是我尝试重构的,在此期间我遇到了所描述的问题。
² 这样做的原因是 D
在 S::split
的多个上下文中使用,它有一些 S
的重载,最重要的是,它经常作为对象传递,非常方便。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)