gpt4 book ai didi

c++ - 如何让 ADL 更喜欢一个函数模板而不是另一个

转载 作者:太空宇宙 更新时间:2023-11-04 14:30:44 24 4
gpt4 key购买 nike

我想知道在其他函数模板可见的情况下,是否可以让 ADL 选择在其中一个参数的类的命名空间(或其他一些明确定义的位置)中定义的函数模板。下面是一个激​​励人心的例子,虽然我知道该特定案例的解决方法(我在下面讨论),但这个问题总体上似乎是有道理的。

我认为避免使用友元声明而是将工作委托(delegate)给方法很酷,因此想出了

namespace n
{
struct a
{
auto swap(a& a2) -> void;
};
auto swap(a& a1, a& a2) -> void
{
a1.swap(a2);
}
}
auto main(void) -> int
{
n::a a1, a2;
using std::swap;
swap(a1,a2); // use case 1
n::swap(a1,a2); // use case 2
}

到目前为止,一切都很好,两个用例都工作正常,但后来,我添加了第二个类,它有自己的交换方法,并决定通过将独立交换转换为模板来节省样板:

namespace n
{
struct a
{
auto swap(a& a2) -> void;
};
struct b
{
auto swap(b& b2) -> void;
};
template<class T>
auto swap(T& t1, T& t2) -> void
{
t1.swap(t2);
}
}
auto main(void) -> int
{
n::a a1, a2;
using std::swap;
swap(a1,a2); // use case 1
n::swap(a1,a2); // use case 2
}

这里用例 1 中断,编译器提示 std::swap 不明确模板。如果预料到这个问题,可以定义 swap函数而不是方法(它们通常是 friend ,因为它们替代了方法):

namespace n
{
struct a
{
friend auto swap(a& a1, a& a2) -> void;
};
struct b
{
friend auto swap(b& b1, b& b2) -> void;
};
}

现在一切正常,所以在 swap 的情况下记住使用友元函数而不是方法就足够了,但是一般情况呢?是否有任何 hack,无论多么肮脏,都可以让编译器明确选择 n::foo<a> (或其他一些 foo<a> 在我们的控制下)在其他 template<class T> foo 的情况下是可见的,要么在全局命名空间中,要么因为某些 using条款,特别是如果后者不是我们要修改的?

最佳答案

这里的罪魁祸首不仅仅是你写了using std::swap , 但从根本上说,您提供了自己的不受限制的函数模板 swap这将给出重载解析错误 std::swap每当namespace std在名称查找期间正在考虑(通过显式 using 指令,或通过 ADL)。

为了说明:只是省略了 using std::swap在这种情况下会救你

Live On Coliru

auto main() -> int
{
n::a a1, a2;
swap(a1,a2); // use case 1
n::swap(a1,a2); // use case 2
}

但是假设你重构了你的类 ab进入类模板b<T>b<T> ,并使用来自 namespace std 的模板参数调用它们(例如 std::string ),然后你会得到一个重载解析错误:

Live On Coliru

#include <iostream>
#include <string>

namespace n
{

template<class>
struct a /* as before */;

template<class>
struct b /* as before */;

}

auto main() -> int
{
n::a<std::string> a1, a2; // oops, ADL will look into namespace std
swap(a1,a2); // use case 1 (ERROR)
n::swap(a1,a2); // use case 2 (OK)
}

结论:如果您定义自己的 swap 版本与 std::swap 具有相同的签名(就重载决议而言),始终限定对它的调用以禁用 ADL。

提示:更好的是,不要偷懒,只需提供您自己的 swap您自己的命名空间中每个类的函数(不是函数模板)。

另见 this Q&A其中解释了为什么提供自己的 begin 不是一个好主意的类似机制。和 end模板并期望它们与 ADL 一起工作。

关于c++ - 如何让 ADL 更喜欢一个函数模板而不是另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34481998/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com