Как написать другую версию алгоритмов STL в C ++? - PullRequest
0 голосов
/ 16 сентября 2011

Для практики я написал несколько template функций, имена которых совпадают с алгоритмами stl.Но мой код не может скомпилировать

ошибка: вызов <имя_ алгоритма> неоднозначен.

Я включил в свой код только using std::necessary_names; вместо using namespace std;.

Ответы [ 3 ]

2 голосов
/ 16 сентября 2011

Обычно, когда у вас есть using, , «используемое» имя имеет приоритет :

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

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

// Output: 0

Однако, зависящий от аргументов поиск может испортить это :

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
}

Итак, если у вас возникли проблемы, определите ваше собственное пространство имен (в данном примере M) явно :

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

В несколько странной ситуации вы также можете использовать скобки для предотвращения 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: поиск безусловного имени] Во всех случаях перечисленные в п. 3.4.1, , в областях ищется объявление в порядок указан в каждой из соответствующих категорий; поиск имени заканчивается как только найдена декларация на имя . Если нет декларации найдена, программа некорректна.

[n3290: 3.4.1/2]: [т.е. первый приоритет] Заявления от пространство имен, назначенное директивой using *, становится видимым в пространстве имен включая директиву об использовании ; см. 7.3.4. Для целей правила поиска имени без оговорок, описанные в п. 3.4.1, объявления из пространства имен, назначенного директивой using члены этого вмещающего пространства имен.

[n3290: 3.4.2/1]: [re: аргумент-зависимый поиск] Когда постфиксное выражение в вызове функции (5.2.2) является безусловным идентификатором , других пространств имен, не рассматриваемых во время обычный неквалифицированный поиск (3.4.1) может быть найден , и в тех пространства имен, объявления дружественных функций в области имен (11.3) not в противном случае видимый может быть найден. Эти модификации в поиске зависит от типов аргументов (и для шаблона шаблона arguments, пространство имен аргумента шаблона).

т.е. Обычный поиск останавливается на имени, которое вы вводите в область действия с помощью using, но когда ADL вступает в игру, другие имена также добавляются в набор кандидатов, вызывая двусмысленность между двумя именами.

0 голосов
/ 16 сентября 2011

Скорее всего, вы столкнулись с проблемой с 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
}
0 голосов
/ 16 сентября 2011

Лучше объявить собственную версию в namespace; чтобы такая проблема не возникала.

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

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

Теперь вы можете сделать,

using std::vector;

, который не будет сталкиваться с MySTL::vector.

...