Неоднозначный член поиска шаблона - PullRequest
0 голосов
/ 04 октября 2018

Ответ на этот вопрос говорит в следующем коде:

#include <vector>
using std::vector;

struct foo {
  template<typename U>
  void vector();
};

int main() {
  foo f;
  f.vector<int>(); // ambiguous!
}

Последняя строка в main неоднозначна, потому что компилятор не только ищет vector в пределах foo, но также и как неквалифицированное имя, начинающееся с main.Таким образом, он находит и std::vector, и foo::vector.Чтобы это исправить, вы должны написать

f.foo::vector<int>();

Я пробовал эту программу на всех популярных компиляторах C ++ (g++, clang++, vc++ и Intel C ++), и все компиляторы компилируют эту программубез ошибок.Итак, почему он сказал, что в этой программе есть двусмысленность?Что стандарт C ++ говорит об этом?

1 Ответ

0 голосов
/ 04 октября 2018

Это было в C ++ 03, но это было исправлено в C ++ 11.Мы даже можем попробовать это жить в Godbolt с Clang, используя флаг -std = c ++ 03 .Мы получаем предупреждение:

<source>:11:5: warning: lookup of 'vector' in member access expression is ambiguous; using member of 'foo' [-Wambiguous-member-template]

  f.vector<int>(); // ambiguous!
    ^

Документация старого лягушки , используя тот же пример из отчета о дефектах ниже при описании предупреждения для -Wambiguous-member-template.

Это былоизменено с помощью отчет о дефекте 1111: удален двойной поиск имен шаблонов элементов , который объясняет проблему:

В соответствии с 6.4.5 [basic.lookup.classref] параграф 1,

В выражении доступа к члену класса (8.2.5 [expr.ref]), если.или -> за маркером сразу же следует идентификатор, за которым следует <, идентификатор необходимо найти, чтобы определить, является ли <начало списка аргументов шаблона (17.2 [temp.names]) или оператор меньше чем.Идентификатор сначала ищется в классе выражения объекта.Если идентификатор не найден, он ищется в контексте всего выражения postfix и должен называть шаблон класса.Если поиск в классе выражения объекта находит шаблон, имя также ищется в контексте всего выражения postfix и </p>

  • , если имя не найдено,используется имя, найденное в классе выражения объекта, в противном случае

  • , если имя найдено в контексте всего выражения postfix и не содержит имени шаблона класса, найденное имяв классе используется выражение объекта, в противном случае

  • , если найденное имя является шаблоном класса, оно должно ссылаться на ту же сущность, что и найденная в классе выражения объектав противном случае программа некорректна.

Это делает следующее некорректное:

#include <set>
using std::set;
struct X {
  template <typename T> void set(const T& value);
};
void foo() {
  X x;
  x.set<double>(3.2);
}

Это сбивает с толку и не нужно.Компилятор уже выполнил поиск в области видимости X, и, очевидно, правильное разрешение таково, а не идентификатор из области видимости выражения postfix.Проблема 305 исправила аналогичную проблему для имен деструкторов, но пропустила функции-члены.

...