如何在c ++中编写不同版本的stl算法?

时间:2011-09-16 12:39:41

标签: c++ stl compiler-errors

为了练习,我写了一些template函数,其名称与stl算法相同。但我的代码无法编译

  

错误:致电< algorithm_name>很暧昧。

我的代码中只包含using std::necessary_names;而不是using namespace std;

3 个答案:

答案 0 :(得分:2)

通常当您有usingthe "used" name takes precedence

namespace N { int x = 0; }
int x = 1;

int main() {
   using N::x;
   cout << x;
}

// Output: 0

但是,依赖于参数的查找can mess this up

namespace N {
   struct T {};
   void f(T) {}
}

namespace M {
    void f(N::T) {}
}

int main() {
   using M::f;
   N::T o;
   f(o);       // <--- error: call of overloaded 'f(N::T&)' is ambiguous
}

所以,如果你遇到麻烦,qualify your own namespace (in this example, M) explicitly

namespace N {
   struct T {};
   void f(T)     { cout << "N::f"; }
}

namespace M {
    void f(N::T) { cout << "M::f"; }
}

int main() {
   using M::f;
   N::T o;
   M::f(o);    // <--- Output: "M::f"
}

有点奇怪的转折,you can also use parentheses to prevent ADL

namespace N {
   struct T {};
   void f(T)     { cout << "N::f"; }
}

namespace M {
    void f(N::T) { cout << "M::f"; }
}

int main() {
   using M::f;
   N::T o;
   (f)(o);     // <--- Output: "M::f"
}

解释

  

[n3290: 3.4.1/1]: [re:unqualified name lookup] 在所有情况下   在3.4.1中列出,在范围内搜索声明   每个类别中列出的订单;名称查找结束   一旦找到名称的声明。如果没有声明   发现,该计划格式不正确。

     

[n3290: 3.4.1/2]: [即第一优先] 来自的声明   由 using-directive 指定的命名空间在命名空间中可见   包含 using-directive ;见7.3.4。出于目的   3.4.1中描述的非限定名称查找规则,声明   从 using-directive 指定的命名空间中考虑   封闭命名空间的成员。

     

[n3290: 3.4.2/1]: [re:argument-dependent lookup] 当函数调用中的 postfix-expression 时   (5.2.2)是一个 unqualified-id 其他名称空间   通常不合格的查询(3.4.1)可能会被搜索,并在那些   名称空间,名称空间范围的朋友函数声明(11.3)不是   否则可见。这些对搜索的修改   取决于参数的类型(以及模板模板)   参数,模板参数的名称空间。)。

即。正常查找将停止在您使用using进入范围的名称中,但是当ADL进入游戏时,其他名称也会添加到候选集中,从而导致两个名称之间存在歧义。

答案 1 :(得分:0)

最好在namespace中声明自己的版本;这样就不会发生这样的问题。

namespace MySTL
{
  template<typename T, ... > // ... means other template params
  class vector;

  template<typename T, ... >
  class queue;
...
}

现在你可以做到,

using std::vector;

不会与MySTL::vector发生冲突。

答案 2 :(得分:0)

您可能会遇到Argument Dependent Lookup的问题。将名称空间中定义的类型传递给非限定函数时,所有参数的名称空间都会隐式添加到查找集中,这可能会导致冲突。您可以尝试限定自己的算法调用以禁止ADL进入。

namespace n {
   struct test {};
   void foo( test const & ) {}
};
int main() {
   n::test t;
   foo( t );    // Will find n::foo as the argument belongs to n namespace
}