支持 argument-dependent 查找的编译器
Compilers that support argument-dependent lookup
在我们的代码库中,我们广泛使用了 boost::intrusive_ptr,在移动了一些 headers 之后,我开始从 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 的代码是不久前编写的,并在 boost
命名空间中定义了所有这些独立函数(如 intrusive_ptr_add_ref
)。在检查了我开始遇到的编译错误的原因之后,看来我应该改为在我的命名空间中定义这些函数。来自 intrusive_ptr 的描述:
On compilers that support argument-dependent lookup,
intrusive_ptr_add_ref
and intrusive_ptr_release
should be defined in
the namespace that corresponds to their parameter; otherwise, the
definitions need to go in namespace boost.
我假设大多数现代编译器都支持 ADL,但是,我找不到关于编译器支持和不支持 ADL 的确切信息。
那么,问题来了:这些不支持 ADL 的编译器是什么。我主要对 Microsoft 编译器(VS2012、VS2015)以及最新版本的 gcc 和 clang 感兴趣。
根据 this page,在 Visual Studio 2008 年添加了 ADL 支持。
虽然有些困难,但我能够构建 EGCS 1.1,这是第一个声称支持名称空间的 GCC 版本,于 1997 年发布。我通过编译和 运行 以下程序对其进行了测试:
#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 构建它们。
在我们的代码库中,我们广泛使用了 boost::intrusive_ptr,在移动了一些 headers 之后,我开始从 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 的代码是不久前编写的,并在 boost
命名空间中定义了所有这些独立函数(如 intrusive_ptr_add_ref
)。在检查了我开始遇到的编译错误的原因之后,看来我应该改为在我的命名空间中定义这些函数。来自 intrusive_ptr 的描述:
On compilers that support argument-dependent lookup,
intrusive_ptr_add_ref
andintrusive_ptr_release
should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace boost.
我假设大多数现代编译器都支持 ADL,但是,我找不到关于编译器支持和不支持 ADL 的确切信息。
那么,问题来了:这些不支持 ADL 的编译器是什么。我主要对 Microsoft 编译器(VS2012、VS2015)以及最新版本的 gcc 和 clang 感兴趣。
根据 this page,在 Visual Studio 2008 年添加了 ADL 支持。
虽然有些困难,但我能够构建 EGCS 1.1,这是第一个声称支持名称空间的 GCC 版本,于 1997 年发布。我通过编译和 运行 以下程序对其进行了测试:
#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 构建它们。