大量 C++ 库(包含标准)允许您调整对象以在库中使用。通常在同一命名空间中的成员函数或自由函数之间进行选择。
我想了解库代码的机制和构造,该库代码用于分派(dispatch)将调用这些“扩展”函数之一的调用,我知道这个决定必须在编译期间发生并且涉及模板。以下运行时伪代码是不可能的/无意义的,原因超出了这个问题的范围。
if Class A has member function with signature FunctionSignature
choose &A.functionSignature(...)
else if NamespaceOfClassA has free function freeFunctionSignature
choose freeFunctionSignature(...)
else
throw "no valid extension function was provided"
上面的代码看起来像运行时代码:/。那么,库如何确定类所在的命名空间,如何检测这三个条件,还有哪些其他需要避免的陷阱。
我提出问题的动机是让我能够在库中找到分派(dispatch) block ,并能够在我自己的代码中使用这些结构。因此,详细的答案会有所帮助。
!!赢得赏金!!
好的,根据 Steve 的回答(和评论)ADL 和 SFINAE 是在编译时连接调度的关键结构。我有我的头脑 arround ADL(原始)和 SFINAE(再次粗鲁)。但我不知道他们是如何以我认为应该的方式协调在一起的。
我想看一个说明性的例子,说明如何将这两个结构放在一起,以便库可以在编译时选择是调用对象中用户提供的成员函数,还是调用对象中用户提供的自由函数对象的命名空间。这应该只使用上面的两个构造来完成,没有任何类型的运行时分派(dispatch)。
假设有问题的对象叫做NS::Car
,这个对象需要提供MoveForward(int units)
的行为,作为c的一个成员函数.如果行为是从对象的命名空间中获取的,它可能看起来像 MoveForward(const Car & car_, int units)
。让我们定义要调度 mover(NS::direction d, const NS::vehicle & v_)
的函数,其中 direction 是一个枚举,而 v_ 是 NS 的基类: :car
.
最佳答案
库在运行时不会做任何这些,调度是由编译器在编译调用代码时完成的。根据称为“参数相关查找”(ADL)(有时称为“Koenig 查找”)的机制规则,在与其中一个参数相同的命名空间中找到自由函数。
在您可以选择实现自由函数或成员函数的情况下,可能是因为库为调用成员函数的自由函数提供了模板。然后,如果您的对象通过 ADL 提供了同名函数,它将比实例化模板更匹配,因此将首先被选中。正如Space_C0wb0y所说,他们可能会使用SFINAE来检测模板中的成员函数,并根据它是否存在来做一些不同的事情。
您无法更改 std::cout << x;
的行为通过向 x
添加成员函数,所以我不太清楚你的意思。
关于c++ - 通过自由函数或成员函数进行扩展的机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5299843/