На выделенную строку студия 2008 ругается, что возникла неоднозначность между std::swap и my::swap в недрах stl.
С одной стороны все вроде бы правильно, но меня это не устраивает, потому, что в NS my я ввел для своих объектов специально, чтобы он не пересекался со стандартным. Можно специализировать std::swap, но я этого не делал, потому что не был уверен, какая версия swap будет вызыватся при использовании различных компиляторов, как довольно старых, так и новых (код работает с GCC от 3.3 до 4.4.1, msvc 2005, на 2008 не компилируется ). Имя swap выбрал для того, чтобы показать, что семантика соответствует std::swap, но работает для объектов из ::my, и когда необходимо, явно специфицировал вызов (::my::swap). Причем, подразумевалось, что если не указано ::my::swap, то должна работать версия std::swap
Как тут поступить?
Почему, хотя шаблоны практически одинаковы (в std::swap используется class вместо typename и шаблон объявлен inline, попробовал поменять свой также — ни чего не поменялось в сообщении) они выводятся компилятором по разному (в моем варианте — как будто два аргумента у шаблона)?
4>c:\program files (x86)\microsoft visual studio 9.0\vc\include\utility(31) : error C2668: 'std::swap' : ambiguous call to overloaded function
4> f:\work\navis\trunk\include\cli\cliutilx.h(994): could be 'void cli::util::swap<_Ty>(IFWrapper &,IFWrapper &)' [found using argument-dependent lookup]
4> with
4> [
4> _Ty=cli::iErrorInfo *,
4> IFWrapper=cli::iErrorInfo *
4> ]
4> c:\program files (x86)\microsoft visual studio 9.0\vc\include\utility(16): or 'void std::swap<_Ty>(_Ty &,_Ty &)'
4> with
4> [
4> _Ty=cli::iErrorInfo *
4> ]
4> while trying to match the argument list '(cli::iErrorInfo *, cli::iErrorInfo *)'
Здравствуйте, Marty, Вы писали:
M>На выделенную строку студия 2008 ругается, что возникла неоднозначность между std::swap и my::swap в недрах stl. M>С одной стороны все вроде бы правильно, но меня это не устраивает, потому, что в NS my я ввел для своих объектов специально, ... M>Как тут поступить?
откажитесь от шаблонов, например http://ideone.com/sqSCA
либо другим методом сделайте ваш swap более специфичным, чтобы он имел приоритет перед std::swap
Здравствуйте, Marty, Вы писали:
M> Здравствуйте, коллеги! M>В начале приведу пример, похожий на мою ситуацию: M>...
M>На выделенную строку студия 2008 ругается, что возникла неоднозначность между std::swap и my::swap в недрах stl. M>С одной стороны все вроде бы правильно, но меня это не устраивает, потому, что в NS my я ввел для своих объектов специально, чтобы он не пересекался со стандартным. Можно специализировать std::swap, но я этого не делал, потому что не был уверен, какая версия swap будет вызыватся при использовании различных компиляторов, как довольно старых, так и новых (код работает с GCC от 3.3 до 4.4.1, msvc 2005, на 2008 не компилируется ). Имя swap выбрал для того, чтобы показать, что семантика соответствует std::swap, но работает для объектов из ::my, и когда необходимо, явно специфицировал вызов (::my::swap). Причем, подразумевалось, что если не указано ::my::swap, то должна работать версия std::swap M>Как тут поступить?
Все очень просто: внутри std::reverse есть обращение к swap с фактическими параметрами типа A&. Поиск подходящей кандидатуры на подстановку выполняется не только в окружающих пространствах имен, но и в пространстве имен фактических параметров. Вот и возникает неоднозначность. Победить легко — достаточно вынести определение класса A в отдельное пространство имен. А чтоб удобно было пользоваться и не пришлось изменять уже существующий код, можно воспользоваться объявлением using:
Здравствуйте, breee breee, Вы писали:
BB>Здравствуйте, Marty, Вы писали:
M>>Как тут поступить?
BB>Например, создать в my вложенное пространство имен и переместить swap туда.
Ну у меня примерно так и сделано:
namespace my{
namespace util{
// template swap goes here
}; // util
using util::swap;
}; // my
Хотелось записи покороче, и она проросла слегка по остальному коду
Здравствуйте, uzhas, Вы писали:
M>>Как тут поступить?
U>откажитесь от шаблонов, например U>http://ideone.com/sqSCA U>либо другим методом сделайте ваш swap более специфичным, чтобы он имел приоритет перед std::swap
Просто функция, перегруженная для каждого типа?
Для многих классов надо делать ;(
А какие еще методы можно использовать?
Здравствуйте, rg45, Вы писали:
R>Все очень просто: внутри std::reverse есть обращение к swap с фактическими параметрами типа A&. Поиск подходящей кандидатуры на подстановку выполняется не только в окружающих пространствах имен, но и в пространстве имен фактических параметров. Вот и возникает неоднозначность. Победить легко — достаточно вынести определение класса A в отдельное пространство имен. А чтоб удобно было пользоваться и не пришлось изменять уже существующий код, можно воспользоваться объявлением using:
Спасибо, идею понял. Много писанины, так же как и в этом
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, breee breee, Вы писали:
BB>>Здравствуйте, Marty, Вы писали:
M>>>Как тут поступить?
BB>>Например, создать в my вложенное пространство имен и переместить swap туда.
M>Ну у меня примерно так и сделано: M>namespace my{ M>namespace util{ M>// template swap goes here M>}; // util M>using util::swap; M>}; // my
M>Хотелось записи покороче, и она проросла слегка по остальному коду
Ну так получается то же самое, только в профиль: при поиске подходящей кандидатуры на подстановку swap внутри std::reverse, она находится в пространстве имен my, благодаря объявлению using. Надо наоборот — swap оставить в my, а class A унести в util:
namespace my{
namespace util{
class A { /*...*/ };
}; // utilusing util::A;
// template swap goes here
}; // my
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Marty, Вы писали:
R>>Все очень просто: внутри std::reverse есть обращение к swap с фактическими параметрами типа A&. Поиск подходящей кандидатуры на подстановку выполняется не только в окружающих пространствах имен, но и в пространстве имен фактических параметров. Вот и возникает неоднозначность. Победить легко — достаточно вынести определение класса A в отдельное пространство имен. А чтоб удобно было пользоваться и не пришлось изменять уже существующий код, можно воспользоваться объявлением using:
M>Спасибо, идею понял. Много писанины, так же как и в этом
способ.
M>Хотелось бы найти максимально красивое решение
Какой писанины? Наоборот, если ты класс A перемещаешь в пространство имен detail окружающий код вообще не меняется, благодаря объявлению using detail::A. А вот если ты в пространство имен detail уносишь swap, то объявлением using detail::swap ты уже воспользоваться не сможешь (потому, что получишь ту же самую ошибку), и везде в вызывающем коде тебе придется вместо my::swap писать my::detail::swap
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
M>>Хотелось записи покороче, и она проросла слегка по остальному коду
R>Ну так получается то же самое, только в профиль: при поиске подходящей кандидатуры на подстановку swap внутри std::reverse, она находится в пространстве имен my, благодаря объявлению using. Надо наоборот — swap оставить в my, а class A унести в util: R>
R>namespace my{
R>namespace util{
R>class A { /*...*/ };
R>}; // util
R>using util::A;
R>// template swap goes here
R>}; // my
R>
если закоментировать using util::swap, то все вроде компилируется.
Тут задумался, а какая версия swap работала раньше при использовании векторов? Похоже что стандартная, и даже странно, что вроде все нормально было. Хотя для обертки operator= перегружен, наверно поэтому. Надо разбиратся, зачем я придумал еще свой swap Выкинуть его вообще, что ли