Koenig查找的基本原理是什么?
无法避免将其视为使您的代码更难以阅读且更不稳定的东西.
他们不能定义Koenig查找,以便它只适用于特定情况(即:非成员运营商)或明确要求时?
我对C++中的标准ADL分辨率有疑问.
以下是解释我的查询的示例代码:
#include <string>
// The mechanism:
namespace A {
template< class C >
::std::string scope(const C*)
{ return "A"; }
namespace B {
template< class C >
::std::string scope(const C *foo)
{ return A::scope(foo)+"::B"; }
} // namespace B
} // namespace A
::std::string scope(...)
{ return ""; }
// The test classes
struct foo {};
namespace A {
struct foo {};
namespace B {
struct foo {};
}
}
// The usage
int main()
{
foo *Foo=0;
A::foo …Run Code Online (Sandbox Code Playgroud) 我有一个问题,我想提供一个函数的泛型版本,foo只有在调用绝对没有其他匹配时才可以应用.我如何修改下面的代码,这样last_resort::foo是更差的比赛derived::type比base::foo?我想找到一个解决方案,它不涉及修改定义, bar而是保留参数的类型last_resort::foo.
#include <iostream>
namespace last_resort
{
template<typename T> void foo(T)
{
std::cout << "last_resort::foo" << std::endl;
}
}
template<typename T> void bar(T)
{
using last_resort::foo;
foo(T());
}
namespace unrelated
{
struct type {};
}
namespace base
{
struct type {};
void foo(type)
{
std::cout << "base::foo" << std::endl;
}
}
namespace derived
{
struct type : base::type {};
}
int main()
{
bar(unrelated::type()); // calls last_resort::foo
bar(base::type()); // …Run Code Online (Sandbox Code Playgroud) 我有两个用于ADL的片段用于演示目的.这两个片段都是由VC10,gcc和comeau C++编译器编译的,结果对于这三个片段都是相同的.
<1> ADL反对使用用户定义的命名空间的指令:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {}
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using M::swap;
N::T o1,o2;
swap(o1,o2);
}
Run Code Online (Sandbox Code Playgroud)
编译结果:
error C2668: 'M::swap' : ambiguous call to overloaded function
could be 'void M::swap(N::T,N::T)'
or 'void N::swap(N::T,N::T)' [found using argument-dependent lookup]
Run Code Online (Sandbox Code Playgroud)
这是预期的,因为ADL不优先于正常查找结果加上ADL不是二等公民,ADL搜索结果与正常(非ADL)无法定义查找联合.这就是为什么我们有歧义.
<2> ADL反对使用std命名空间的指令:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {} //point 1
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{ …Run Code Online (Sandbox Code Playgroud) 诸如启用std类型输出之类的示例解释了如何使用ADL来“注入”某个函数/运算符,具体取决于 fn/op 应用到的类型。
我想知道 ADL 是否完全适用于全局命名空间,也就是说,using在全局命名空间范围内声明(或通过 提供)的类型是否使 ADL在全局命名空间中寻找匹配的函数?
具体来说,这些是等价的。ADL?:
// 1 - at global namespace scope
struct GlobalType {};
template< class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, GlobalType const& x)
{
os << ...;
return os;
}
// 2 - within namespace
namespace ecaps {
struct EcapsType {};
template< class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, EcapsType const& x)
{
os << ...; …Run Code Online (Sandbox Code Playgroud) c++ namespaces using global-namespace argument-dependent-lookup
这是一个例子:
#include <string>
#include <algorithm>
#include <memory>
using std::string;
int main()
{
string str = "This is a string";
// ok: needn't using declaration, ADL works
auto it = find(str.begin(), str.end(), 'i');
// error: why ADL doesn't work?
std::shared_ptr<string> sp = make_shared<string>(str);
}
Run Code Online (Sandbox Code Playgroud)
当我试图编译这个程序时,编译器抱怨:
error: no template named 'make_shared'; did you mean 'std::make_shared'?
std::shared_ptr<string> sp = make_shared<string>(str); // error...
^~~~~~~~~~~
std::make_shared
Run Code Online (Sandbox Code Playgroud)
我猜第一个函数find不需要using声明,因为依赖于参数的lookup(ADL):编译器会搜索名称空间string(即std)的定义find.但对于第二个函数make_shared,它似乎ADL不起作用:我必须使用std::make_shared或 …
我刚刚使用参数依赖查找遇到了一些有趣的行为,我不完全理解:
#include <iostream>
namespace a {
struct Foo {
Foo(int v1, int v2) : v1(v1), v2(v2) { }
int v1,v2;
};
}
namespace b {
template <typename T>
struct Baz : T {
using T::T;
};
}
namespace c {
using Foo = ::b::Baz< ::a::Foo>;
// (1) NOT FOUND BY ADL
// std::ostream& operator << (std::ostream& os, const Foo& foo)
// {
// return os << foo.v1 << "," << foo.v2;
// }
}
namespace b {
// (2) FOUND …Run Code Online (Sandbox Code Playgroud) 考虑以下代码片段:
#include <functional>
namespace ns {
struct Arg{};
using Func = std::function<int(Arg)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, rhs](Arg arg) {
return lhs(arg) + rhs(arg);
};
}
}
int main() {
ns::Func foo = [](ns::Arg i) {return 5;};
ns::Func bar = [](ns::Arg i) {return 2;};
auto foobar = foo + bar;
return foobar(ns::Arg());
}
Run Code Online (Sandbox Code Playgroud)
上面的代码使用各种编译器进行编译。相反,以下代码段不会编译。唯一的区别是Func(Argvs int)内部使用的参数类型:
#include <functional>
namespace ns {
using Func = std::function<int(int)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, …Run Code Online (Sandbox Code Playgroud) 实际上,使用此命令无法使用 Clang 编译以下代码:
clang++ -std=c++11 test.cc -o test.
我只想模仿与 C++ 中的“交换习语”相同的行为,以使用“使用指令”来启用 ADL。但是下面的代码我哪里错了?预期的呼叫优先级应该是:N1::foo> N2::foo> ::foo,对吗?
namespace N1 {
struct S {};
void foo(S s) {
std::cout << "called N1::foo.";
}
}
namespace N2 {
void foo(N1::S s) {
std::cout << "called N2::foo.";
}
}
void foo(N1::S s) {
std::cout << "called foo.";
}
int main() {
using N2::foo;
foo(N1::S{});
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
test.cc:54:3: error: call to 'foo' is ambiguous
foo(N1::S{});
^~~
test.cc:40:8: note: candidate function
void foo(S …Run Code Online (Sandbox Code Playgroud) struct A
{
enum InnerEnum { X };
A(InnerEnum x)
{}
};
int main()
{
A a(X);
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨: error C2065: 'X' : undeclared identifier
编译器知道构造函数的参数类型是什么,因此当我将X作为参数传递时,编译器应该知道它是一个有效的参数.
我知道这不是ADL(Argument-dependent Name Lookup,也称为Koenig Lookup),但我认为它很有用且非常方便.因为我不必写如下:
A a(A::X);
Run Code Online (Sandbox Code Playgroud)
我认为ADL规则应该推广到这种情况.
我对吗?
c++ ×10
namespaces ×3
name-lookup ×2
templates ×2
c++11 ×1
rationale ×1
standards ×1
std-function ×1
using ×1