开发者

How to write a different version of stl algorithms in c++?

开发者 https://www.devze.com 2023-04-05 03:44 出处:网络
For practice, I wrote some template functions whose names are the same as the stl algorithms. But my code can not compile

For practice, I wrote some template functions whose names are the same as the stl algorithms. But my code can not compile

error: Call to < algorithm_name > is ambiguous.

I only开发者_如何学编程 included using std::necessary_names; in my code rather than using namespace std;.


Usually when you have using, the "used" name takes precedence:

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

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

// Output: 0

However, Argument-Dependent Lookup 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
}

So, if you are having trouble, 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"
}

In a somewhat bizarre twist, 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"
}

Explanation

[n3290: 3.4.1/1]: [re: unqualified name lookup] In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.

[n3290: 3.4.1/2]: [i.e. first priority] The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see 7.3.4. For the purpose of the unqualified name lookup rules described in 3.4.1, the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.

[n3290: 3.4.2/1]: [re: argument-dependent lookup] When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function declarations (11.3) not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument).

i.e. Normal lookup stops at the name that you brought into scope with using, but when ADL comes into play, other names are also added to the candidate set, causing an ambiguity between two names.


It's better to declare your own version in a namespace; so that such problem would not occur.

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

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

now you can do,

using std::vector;

which will not collide with MySTL::vector.


Chances are that you are hitting a problem with Argument Dependent Lookup. When you pass a type that is defined within a namespace to an unqualified function, the namespaces of all the arguments are implicitly added to the lookup set, and that might cause collisions. You can try to qualify your own algorithm calls to inhibit ADL from kicking in.

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
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号