В моей библиотеке при переходе на версию STL из поставки VS2005 (с STLPort все в порядке)
полезли ошибки компиляции. Вот минимальный код, приводящий к ошибке
Проблема в выражении begin() + _Newsize и заключается в том, что _Newsize имеет тип size_type, а для итератора, возаращаемого begin() операция сложения определена так:
Что делает компилятор: он считает, что вместо преобразования size_type->difference_type [это преобразование unsigned int->int для того чтобы
вызвать operator+(difference_type _Off) const ] более подходящим являетя мой шаблонный!! оператор Expression<Left, Right> operator + (Left const& a, Right const& b ),
который он и подставляет. Дальше все по плану: Expression<Left, Right> не возможно превести к std::vector<>::iterator, который требуется для вызова erase(...)
Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют?
Вопрос 2. Почему если внутри resize (для вызова begin() + _Newsize) требуется приведение типа разработчики на сделали это явно (это конечно если компилятор прав в первом вопросе)?
Вопрос 3. Что делать? Править исходник вектора не хочется.
ps: с STLPort все в порядке потому, что в векторе итератор это просто голый указатель. С ним у компилятора вопросов не возникает.
Re: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, Kazmerchuk Pavel, Вы писали:
KP>Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют?
Компилятор прав. Посколько vector::iterator наследуется от шаблона std::iterator, поиск (ADL) проводится также в пространствах имен параметров шаблона. Первый из списка параметров std::iterator как раз Ваш mtr::Matrix.
KP>Вопрос 2. Почему если внутри resize (для вызова begin() + _Newsize) требуется приведение типа разработчики на сделали это явно (это конечно если компилятор прав в первом вопросе)?
В стандарте поведение resize задается как:
if (sz > size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end()); // приведения нетelse
; //do nothing
KP>Вопрос 3. Что делать? Править исходник вектора не хочется.
Думаю лучше объявить менее "шаблонную" функцию operator+. К примеру оставить один параметр в шаблоне.
KP>ps: с STLPort все в порядке потому, что в векторе итератор это просто голый указатель. С ним у компилятора вопросов не возникает.
Правильно, у итератора в этом случает нет предка-шаблона.
Re[2]: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, Greg Zubankov, Вы писали:
KP>>Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют? GZ>Компилятор прав. Посколько vector::iterator наследуется от шаблона std::iterator, поиск (ADL) проводится также в пространствах имен параметров шаблона. Первый из списка параметров std::iterator как раз Ваш mtr::Matrix.
а разве сначала не производится обычный поиск в пространстве std (где определены vector::iterator и std::iterator) ?
Re[3]: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, night beast, Вы писали:
KP>>>Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют? GZ>>Компилятор прав. Посколько vector::iterator наследуется от шаблона std::iterator, поиск (ADL) проводится также в пространствах имен параметров шаблона. Первый из списка параметров std::iterator как раз Ваш mtr::Matrix.
NB>а разве сначала не производится обычный поиск в пространстве std (где определены vector::iterator и std::iterator) ?
Я написал "проводится также". Естественно сначала проводится ordinary unqualified lookup. Затем проводится ADL. Из двух найденных operator+ однозначно выбирается mtr::operator+.
Clause 3.4.2 verse 2a:
If the ordinary unqualified lookup of the name finds the declaration of a class member function, the associated
namespaces and classes are not considered. Otherwise the set of declarations found by the lookup of
the function name is the union of the set of declarations found using ordinary unqualified lookup and the set
of declarations found in the namespaces and classes associated with the argument types.
PS. если бы vector::iterator::operator+ был объвлен без квалификатра const, компилятор выдал бы ошибку неоднозначности выбора
Re[4]: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, Greg Zubankov, Вы писали:
GZ>Здравствуйте, night beast, Вы писали:
KP>>>>Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют? GZ>>>Компилятор прав. Посколько vector::iterator наследуется от шаблона std::iterator, поиск (ADL) проводится также в пространствах имен параметров шаблона. Первый из списка параметров std::iterator как раз Ваш mtr::Matrix.
NB>>а разве сначала не производится обычный поиск в пространстве std (где определены vector::iterator и std::iterator) ?
GZ>Я написал "проводится также". Естественно сначала проводится ordinary unqualified lookup. GZ>Затем проводится ADL. Из двух найденных operator+ однозначно выбирается mtr::operator+.
это я к тому что begin() + _Newsize вызавается в пространстве std, и по идее до ADL дело не должно было дойти.
или я не прав?
Re[5]: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, night beast, Вы писали:
NB>это я к тому что begin() + _Newsize вызавается в пространстве std, и по идее до ADL дело не должно было дойти. NB>или я не прав?
ADL проводится вне зависимости от кого, в какой область видимости (scope) компилятору встретилось неквалифицированное имя.
PS. Однако есть способ отключения ADL, для этого достаточно заключить имя вызываемой функции в скобки:
Здравствуйте, Greg Zubankov, Вы писали:
GZ>ADL проводится вне зависимости от кого, в какой область видимости (scope) компилятору встретилось неквалифицированное имя.
У Вандервуда с Джосаттисом: "Если при обычном поиске будет найдено имя функции-члена или имя типа, то ADL не применяется."
_Myt operator+(difference_type _Off) const
как раз является членом std::vector<...>::iterator. Как это объяснить?
Re[7]: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, Kazmerchuk Pavel, Вы писали:
KP>У Вандервуда с Джосаттисом: "Если при обычном поиске будет найдено имя функции-члена или имя типа, то ADL не применяется."
KP>
KP>_Myt operator+(difference_type _Off) const
KP>
KP> как раз является членом std::vector<...>::iterator. Как это объяснить?
В том и дело, что имя функции-члена не было найдено, а найдено было выражение begin() + _Newsize.
Как интерпретируются такие выражения расписано в 13.3.1.2/2
For a unary operator @ with an operand of a type whose cv-unqualified version is T1, and for a binary operator
@ with a left operand of a type whose cv-unqualified version is T1 and a right operand of a type whose
cv-unqualified version is T2, three sets of candidate functions, designated member candidates, non-member
candidates and built-in candidates, are constructed as follows:
...
Re[2]: ADL. Кто неправ я, компилятор или реализация STL
Почему нет приведения? sz имеет тип size_type (что есть — unsigned int)
operator+ для итератора принимает difference_type (что есть int). Компилятор должен выполнить интегральное преобразование unsigned int -> int, чтобы вызвать iterator::operator+. Или я не прав?
p.s. я это к тому, что явное приведение sz к difference_type решает мою проблему.
Re: ADL. Кто неправ я, компилятор или реализация STL
Здравствуйте, Kazmerchuk Pavel, Вы писали:
KP>Почему нет приведения? sz имеет тип size_type (что есть — unsigned int) KP>operator+ для итератора принимает difference_type (что есть int). Компилятор должен выполнить интегральное преобразование unsigned int -> int, чтобы вызвать iterator::operator+. Или я не прав?
Я наверное не слишком понятно выразился.
Хотел сказать что в стандарте нет указания делать явное приведение. Естественно при вызове функции iterator::operator+ (в случае ее выбора), компилятор произведет неявное преобразование.
KP>p.s. я это к тому, что явное приведение sz к difference_type решает мою проблему.
Да, согласен.