在我们的代码库中,我们广泛使用boost::intrusive_ptr,在移动了一些标题后,我开始从clang中获得意外的编译错误:
In file included from C:/code/Signal.cpp:1:
In file included from C:/code/signal.h:3:
In file included from c:/boost_1_56_0/include/boost/smart_ptr.hpp:26:
In file included from c:/boost_1_56_0/include/boost/intrusive_ptr.hpp:16:
c:/boost_1_56_0/include/boost/smart_ptr/intrusive_ptr.hpp:68:34: error: call to function 'intrusive_ptr_add_ref' that is neither visible in the template definition nor found by argument-dependent lookup
if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
有similar issues reported elsewhere。
我们前一段时间编写了使用boost::intrusive_ptr的代码,并在intrusive_ptr_add_ref
命名空间中定义了所有这些独立函数(如boost
)。在检查了我开始得到的编译错误的原因后,似乎我应该在我的命名空间中定义这些函数。来自description of intrusive_ptr:
在支持argument-dependent lookup的编译器上, 应在
intrusive_ptr_add_ref
和intrusive_ptr_release
中定义 与其参数对应的命名空间;否则, 定义需要进入名称空间提升。
我认为大多数现代编译器都支持ADL,但是,我无法找到关于编译器支持什么以及什么不支持ADL的确切信息。
所以,问题在于:这些编译器不支持ADL。我主要对微软编译器(VS2012,VS2015)以及最新版本的gcc和clang感兴趣。
答案 0 :(得分:0)
根据this page,在Visual Studio 2008中添加了ADL支持。
有一些困难,我能够构建EGCS 1.1,这是1997年发布的第一个声称支持命名空间的GCC版本。我通过编译并运行以下程序来测试它:
#include <stdio.h>
namespace foo {
class bar {};
void baz(bar&) {
puts("foo::baz");
}
}
void baz(const foo::bar&) {
puts("::baz");
}
int main() {
foo::bar bar;
baz(bar);
}
打印foo::baz
,这是正确的。因此,即使在那些日子里,GCC也存在基本的ADL功能。我怀疑你甚至可以使用旧的编译器来构建Boost。
Clang 2.7也是对的。请注意,2010年发布的LLVM 2.7是默认情况下在Clang中启用C ++支持的第一个LLVM版本。有一些旧版本的Clang C ++前端,但我不认为它们被广泛使用,而且我太懒了,不能尝试从SVN构建它们。