ADL与当前名称空间中的功能发生冲突
我的命名空间中有一个功能。它的名称是<代码>销毁。 std
命名空间还包含 and nofollow noreferrer' 。当我在命名空间中调用我的功能时,调用是模棱两可的,因为std :: destroy
也添加到通过参数依赖的查找设置的过载分辨率中。
#include <string>
#include <memory>
namespace my {
template <typename TIter>
void destroy(TIter it_begin, TIter it_end) noexcept
{
// Dummy
}
void func(std::string *p_begin, std::string *p_end)
{
destroy(p_begin, p_end);
}
}
以上代码未能 compile 。
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'void my::func(std::string*, std::string*)':
main.cpp:14:16: error: call of overloaded 'destroy(std::string*&, std::string*&)' is ambiguous
14 | destroy(p_begin, p_end);
| ~~~~~~~^~~~~~~~~~~~~~~~
main.cpp:7:10: note: candidate: 'void my::destroy(TIter, TIter) [with TIter = std::__cxx11::basic_string<char>*]'
7 | void destroy(TIter it_begin, TIter it_end) noexcept
| ^~~~~~~
/usr/local/include/c++/11.2.0/bits/stl_construct.h:240:5: note: candidate: 'void std::destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::__cxx11::basic_string<char>*]'
240 | destroy(_ForwardIterator __first, _ForwardIterator __last)
| ^~~~~~~
好的,在调用此功能时,我可以明确指定名称空间:my :: destion(p_begin,p_end)
。但这不是通用解决方案。想象一下,我添加了一个函数void ababaken(std :: string)
,但后来具有相同名称的函数将添加到std
中。我的代码将再次产生汇编错误。而且我不想明确指定每个功能调用的命名空间。
当std
函数被ADL捕获时,我还能做些什么来避免使用std
namepace的歧义?如何防止ADL?
I have a function in my namespace. Its name is destroy
. std
namespace also contains a function with this name. When I call my function within my namespace, the call is ambiguous, because std::destroy
is also added to overload resolution set by argument dependent lookup.
#include <string>
#include <memory>
namespace my {
template <typename TIter>
void destroy(TIter it_begin, TIter it_end) noexcept
{
// Dummy
}
void func(std::string *p_begin, std::string *p_end)
{
destroy(p_begin, p_end);
}
}
The code above fails to compile.
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'void my::func(std::string*, std::string*)':
main.cpp:14:16: error: call of overloaded 'destroy(std::string*&, std::string*&)' is ambiguous
14 | destroy(p_begin, p_end);
| ~~~~~~~^~~~~~~~~~~~~~~~
main.cpp:7:10: note: candidate: 'void my::destroy(TIter, TIter) [with TIter = std::__cxx11::basic_string<char>*]'
7 | void destroy(TIter it_begin, TIter it_end) noexcept
| ^~~~~~~
/usr/local/include/c++/11.2.0/bits/stl_construct.h:240:5: note: candidate: 'void std::destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::__cxx11::basic_string<char>*]'
240 | destroy(_ForwardIterator __first, _ForwardIterator __last)
| ^~~~~~~
Ok, I can explicitly specify namespace when calling this function: my::destroy(p_begin, p_end)
. But that's not a generic solution. Imagine I add a function void ababaken(std::string)
but later a function with the same name is added to std
. My code will produce compilation error again. And I do not want to explicitly specify namespace for every function call.
What else can I do to avoid ambiguity with std
namespace when std
function is caught up by ADL? How can I prevent ADL?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您不想装饰所有通话,则可以:
如果您是一次性解决方案,则可以:
(destion)(p_begin,p_end);
围绕括号中的函数名称。my :: destion(p_begin,p_end);
正如您所说的,合格的名称也有效。If you don't want to decorate every call, you can:
If you one a one-off solution, you can:
(destroy)(p_begin, p_end);
Surround the function name in parentheses.my::destroy(p_begin, p_end);
As you said, a qualified name also works.您只有冲突,因为 参数和在命名空间
std
中声明了函数。ADL不会引起
MY :: DESTION
和std :: Destry
之间的冲突。因此,以下内容是完全可以的:您特别有问题,因为您想在命名空间
std
中声明的对象上my :: destion
。这就是为什么在
std :: String
上添加我的
命名空间范围的分辨率是 destion 是最好的解决方案。不用担心未来。您无法预测。如果标准库的未来版本添加了类或函数,其名称与代码中的内容相同,那么您可能会有更多的问题。
坦率地说,未来的编译器错误比默默地选择错误函数过载的编译器要好得多。
You only have a conflict because both the argument and the function are declared in namespace
std
.ADL doesn't cause a conflict between
my::destroy
andstd::destroy
if the argument isn't declared innamespace std
. So, the following is perfectly OK:You specifically have a problem because you want to
my::destroy
on objects declared in namespacestd
.This is why adding the
my
namespace scope resolution to the specific instance of callingdestroy
onstd::string
is the best solution.Don't worry about the future. You can't predict it. If a future version of the standard library adds a class or function with the same name as something in your code, you are likely to have more problems than just this.
And frankly, a future compiler error is a far better proposition than the compiler silently selecting the wrong function overload.