Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Поиск имени в пространстве имён


Автор: zim22 14.7.2009, 19:37
Как сделать, чтобы вызывался operator== из His_lib?
Можно его явно вызывать(закомментированная строчка в коде), но некрасиво как-то...
При попытке добавить 
Код

using His_lib::operator==;
d == 5;

компилятор ругается : error C2593: 'operator ==' is ambiguous
Код

namespace Chrono {
  class Date { };
  bool operator==(const Date&, int) { return true; }
}

namespace His_lib {
  using namespace Chrono;
  bool operator==(const Date&, int) { return false; }
}


int main()
{  
  His_lib::Date d;
  d == 5; // call Chrono::operator==
  // His_lib::operator==(d, 5);
  return 0;
}

Автор: ISergeyN 14.7.2009, 19:59
А если так сделать
Код

#include <iostream>

class Date { };

namespace Chrono {
    bool operator==(const Date&, int) { return true; }
}

namespace His_lib {
    bool operator==(const Date&, int) { return false; }
}

using His_lib::operator ==;
//using Chrono::operator ==;
int main()
{  
    Date d;

    if(d == 5) 
        std::cout << "namespace Chrono\n";
    else
        std::cout << "namespace His_lib\n";

    return 0;
}

Автор: zim22 14.7.2009, 20:04
Цитата(ISergeyN @  14.7.2009,  19:59 Найти цитируемый пост)
А если так сделать

не жульничайте!  smile  всё, что находится внутри namespaces - священно! структуру нельзя менять  smile 

Автор: azesmcar 14.7.2009, 20:13
zim22

Ну так тут два, абсолютно идентичных (по сигнатуре) оператора сравнения. Используя тип Date вы заставляете компилятор искать оператор и в его пространстве имен, как следствие этого
Если
using His_lib::operator ==; написан - он видет два оператора, если нет - видит один и вызывает его из пространства имен Chrono.
Код

namespace Chrono {
    class Date { };
    bool operator==(const Date&, int) { return true; }
}
namespace His_lib {
    class Date {} ;
    bool operator==(const Date&, int) { return false; }
}

Вот так он сработает.
Код

namespace Chrono {
    class Date { };
    bool operator==(const Date&, int) { return true; }
}
namespace His_lib {
    class Date : Chrono::Date {} ;
    bool operator==(const Date&, int) { return false; }
}

но это уже извращения..а можно узнать зачем это нужно? По идее вы пишите два оператора сравнения для одного и того же класса, в разных неймспейсах..и притом хотите чтобы поиск шел в обоих из них. Непонятно smile 

Еще как вариант.
Код

namespace Chrono {
    class Date { };
    namespace {
        bool operator==(const Date&, int) { return true; }
    }
}
namespace His_lib {
    typedef Chrono::Date Date;
    namespace {
        bool operator==(const Date&, int) { return false; }
    }
}

using His_lib::operator ==;
//using Chrono::operator ==;

Автор: zim22 14.7.2009, 20:44
Цитата(azesmcar @  14.7.2009,  20:13 Найти цитируемый пост)
? По идее вы пишите два оператора сравнения для одного и того же класса, в разных неймспейсах..

 smile 
Цитата(azesmcar @  14.7.2009,  20:13 Найти цитируемый пост)
и притом хотите чтобы поиск шел в обоих из них

а вот этого я не хотел. я хотел явно указать, чтобы вызывался His_lib::operator==

Цитата(azesmcar @  14.7.2009,  20:13 Найти цитируемый пост)
.а можно узнать зачем это нужно?

Я хочу использовать существующий класс Date, но со своей, переопределённой операцией сравнения, т.к. меня не устраивает operator== из Chrono, а переписать его я не могу -   компьютер взорвётся smile

Для логической связности данных я создаю namespace His_Lib, указываю в нём, что я буду пользоваться классом Date из Chrono
Код

using namespace Chrono;

хотя не совсем хорошо указываю, более правильно было бы так:
Код

namespace His_lib {
  using Chrono::Date;
  bool operator==(const Date&, int) { return false; }
}

и определяю СВОЙ оператор сравнения. но он не вызывается...  smile 
а вызывается 
Код

d == 5; // call Chrono::operator== 

***
ваш 1 вариант не подходит: два разных класса Date создаётся
2 вариант тоже не подходит: создаётся новый класс Date
3 вариант - подходит!  smile но он неочевидный какой-то. использовать анонимное пространство имён, чтобы ограничить область видимости оператора... хотя может это и нормально...

Автор: azesmcar 14.7.2009, 20:48
Цитата(zim22 @  14.7.2009,  20:44 Найти цитируемый пост)
а вот этого я не хотел. я хотел явно указать, чтобы вызывался His_lib::operator==

Ну, хотел не хотел а это так smile 
Поиск идет также в пространстве имен аргументов функции/оператора. 

Цитата(zim22 @  14.7.2009,  20:44 Найти цитируемый пост)
ваш 1 вариант не подходит: два разных класса Date создаётся
2 вариант тоже не подходит: создаётся новый класс Date

Ну да, разумеется..я просто для примера показал, чтобы причина нагляднее была.

Автор: Леопольд 15.7.2009, 11:31
Цитата(zim22 @ 14.7.2009,  19:37)
Как сделать, чтобы вызывался operator== из His_lib?
Можно его явно вызывать(закомментированная строчка в коде), но некрасиво как-то...
При попытке добавить 
Код

using His_lib::operator==;
d == 5;

компилятор ругается : error C2593: 'operator ==' is ambiguous

using His_lib::operator==; делает видимым этот оператор в глобальном пространстве имён. ADL находит operator== в том пространстве имён где определён класс Date, т.е. в Chrono. Следовательно, компилятор пытается разобраться какую из функций вызвать. Но, так-как они имеют абсолютно одинаковую сигнатуру, получается неоднозначность вызова. Такая перегрузка не может быть разрешена.

Автор: zim22 15.7.2009, 11:42
Цитата(Леопольд @  15.7.2009,  11:31 Найти цитируемый пост)
Но, так-как они имеют абсолютно одинаковую сигнатуру, получается неоднозначность вызова. Такая перегрузка не может быть разрешена

то, что два operator== имеют одинаковую сигнатуру - не является поводом для неоднозначного вызова.
компилятор в состоянии разрешить эту однозначность, если ему помочь.
Код

namespace First {
  class Date { };
  int value;
};

namespace Second {
  class Date { };
  int value;
};

namespace Mine {
  using namespace First;
  using namespace Second;

  using First::Date;   // помогаем
  using Second::value; // помогаем
}

int main() {
  Mine::Date d1;     
  Mine::value = 15;
}

если строчки "// помогаем" закомментировать - то будет ambiguos call

Автор: Леопольд 15.7.2009, 11:55
Цитата(zim22 @ 15.7.2009,  11:42)
если строчки "// помогаем" закомментировать - то будет ambiguos call

Не будет, потому что здесь нет вызова функции. Будут другие ошибки, не связанные с разрешением перегрузки.

Я имел ввиду следующее.
Код

namespace First {
    class Class {};
    void func(Class const&) {
        std::cout<<"First::func(Class const&)"<<std::endl;
    }
};

void func(First::Class const&){
    std::cout<<"::func(Class const&)"<<std::endl;
}

int main() {
//  using First::func; без этого будет неоднозначность вызова.
    First::Class c;
    func(c);
}

Автор: zim22 15.7.2009, 12:04
Цитата(Леопольд @  15.7.2009,  11:55 Найти цитируемый пост)
 Будут другие ошибки, не связанные с разрешением перегрузки.

ambiguos symbol будет smile
я даже и не думал, что проблема в перегрузке функции. думал - конфликт namespace. спасибо.
разные типы возвращаемых значений и параметров у operator== поставил - и компилятор начал находить нужные функции.
Код

#include <string>

namespace Chrono {
  class Date { };
  bool operator==(const Date&, int) { return true; }
}

namespace His_lib {
  using Chrono::Date;
  int operator==(const Date&, std::string&) { return 5; }
}

int main()
{  
  His_lib::Date d;  
  using His_lib::operator==;
  d == std::string("hi");    
}


Автор: azesmcar 15.7.2009, 12:26
Цитата(zim22 @  15.7.2009,  12:04 Найти цитируемый пост)
разные типы возвращаемых значений и параметров у operator== поставил - и компилятор начал находить нужные функции.

А причем тут возвращаемый тип? Функции по возвращаемому типу не перегружаются, перегрузка в вашем случае произошла по второму аргументу оператора ==. Возвращаемый тип функции не является частью ее сигнатуры.
Цитата

Function signatures do not include return type, because that does not participate in overload resolution.


Цитата(zim22 @  15.7.2009,  12:04 Найти цитируемый пост)
я даже и не думал, что проблема в перегрузке функции. думал - конфликт namespace. спасибо.

там не было перегрузки, там были

Цитата(azesmcar @  14.7.2009,  20:13 Найти цитируемый пост)
два, абсолютно идентичных (по сигнатуре) оператора сравнения

и компилятор не знал какой из них вызывать, потому и ambiguous (неоднозначность). 

Автор: Леопольд 15.7.2009, 12:33
Цитата(azesmcar @ 15.7.2009,  12:26)
А причем тут возвращаемый тип? Функции по возвращаемому типу не перегружаются, перегрузка в вашем случае произошла по второму аргументу оператора ==. Возвращаемый тип функции не является частью ее сигнатуры.

Насколько я помню, возвращаемый тип имеет значение для операторов преобразования типа, но они настолько специальные что на это можно "эакрыть глаза".

Автор: azesmcar 15.7.2009, 12:43
Цитата(Леопольд @  15.7.2009,  12:33 Найти цитируемый пост)

Насколько я помню, возвращаемый тип имеет значение для операторов преобразования типа, но они настолько специальные что на это можно "эакрыть глаза". 

речь о user-defined conversions?
Код

class A
{
private:
    int i_;
public:
    A(int i): i_(i) {}
    operator int() const {
        return i_;
    }
};

для них не указывается возвращаемый тип и его нелзя изменить, возвращаемый тип всегда тот, для которого оператор написан.

Автор: zim22 15.7.2009, 13:21
Цитата(azesmcar @  15.7.2009,  12:26 Найти цитируемый пост)
там не было перегрузки, там были два, абсолютно идентичных (по сигнатуре) оператора сравнения

да, точно. туплю что-то... smile

Автор: Леопольд 15.7.2009, 14:17
Цитата(azesmcar @ 15.7.2009,  12:26)
там не было перегрузки, там были
Цитата(azesmcar @  14.7.2009,  20:13 Найти цитируемый пост)
два, абсолютно идентичных (по сигнатуре) оператора сравнения

и компилятор не знал какой из них вызывать, потому и ambiguous (неоднозначность).

Вроде бы "перегрузка" означает несколько функций с одинаковым именем, видимых в точке вызова. Если у пары (или больше) из них будет одинаковая сигнатура, то перегрузка не может быть разрешена однозначно. Т.е. здесь как раз возникла неоднозначность из-за того что "видны" две функции с одинаковым именем и одинаковой сигнатурой. Если это не перегрузка operator==, то как это ещё обозвать? smile

Автор: azesmcar 15.7.2009, 14:27
Цитата(Леопольд @  15.7.2009,  14:17 Найти цитируемый пост)
Вроде бы "перегрузка" означает несколько функций с одинаковым именем, видимых в точке вызова. 


Ну, называться то она называется
Цитата

When two or more different declarations are specified for a single name in the same scope, that name is
said to be overloaded.


только вот в правильно составленной программе такой перегрузки быть не может
Цитата

Not all function declarations can be overloaded. Those that cannot be overloaded are specified here. A
program is ill-formed if it contains two such non-overloadable declarations in the same scope.


Автор: Леопольд 15.7.2009, 14:33
Цитата(azesmcar @ 15.7.2009,  14:27)
Ну, называться то она называется
...
только вот в правильно составленной программе такой перегрузки быть не может

Просто хотелось внести ясность и назвать вещи своими именами.

Добавлено @ 14:36
Цитата(azesmcar @ 15.7.2009,  14:27)
Цитата

Not all function declarations can be overloaded. Those that cannot be overloaded are specified here. A
program is ill-formed if it contains two such non-overloadable declarations in the same scope.

Честно говоря, не понял о чём речь. Может, потому что цитата не имеет контекста?

Автор: azesmcar 15.7.2009, 14:39
Цитата(Леопольд @  15.7.2009,  14:33 Найти цитируемый пост)
Честно говоря, не понял о чём речь.  

Перевод: Не всякие декларации функций могут быть перегружены.

Цитата(Леопольд @  15.7.2009,  14:33 Найти цитируемый пост)
Может, потому что цитата не имеет контекста?

почему же нет? вот контекст
Цитата(azesmcar @  15.7.2009,  14:27 Найти цитируемый пост)
только вот в правильно составленной программе такой перегрузки быть не может


Автор: Леопольд 15.7.2009, 14:42
Цитата(azesmcar @ 15.7.2009,  14:39)
Цитата(Леопольд @  15.7.2009,  14:33 Найти цитируемый пост)
Честно говоря, не понял о чём речь.  

Перевод: Не всякие декларации функций могут быть перегружены.

Цитата(Леопольд @  15.7.2009,  14:33 Найти цитируемый пост)
Может, потому что цитата не имеет контекста?

почему же нет? вот контекст
Цитата(azesmcar @  15.7.2009,  14:27 Найти цитируемый пост)
только вот в правильно составленной программе такой перегрузки быть не может

Погуглил и понял о чём речь smile
http://www.kuzbass.ru/docs/isocpp/over.html
Есть ограничения на перегрузку. Но это, вроде, не "наш" случай.

Автор: azesmcar 15.7.2009, 14:59
Леопольд

Перегрузка функции осуществляется "по чему-то". По количеству аргументов, по типу аргументов, итд...
Если две функции абсолютно идентичны - это называется redefinition, такой перегрузки быть не может по идее.

Добавлено через 2 минуты
Вот, покопался. Для примера, как это называет стандарт
Цитата(Стандарт)

typedef int Int;
void f(int i);
void f(Int i); // OK: redeclaration of f(int)
void f(int i) { /* ... */ }
void f(Int i) { /* ... */ } // error: redefinition of f(int)


Автор: Леопольд 15.7.2009, 15:20
Цитата(azesmcar @ 15.7.2009,  14:59)
Перегрузка функции осуществляется "по чему-то". По количеству аргументов, по типу аргументов, итд...
Если две функции абсолютно идентичны - это называется redefinition, такой перегрузки быть не может по идее.

Если взглянуть с этой стороны, то это нарушение ODR. Так, наверное, действительно будет правильнее.

На всякий случай добавлю что из ODR тоже есть исключения. Например, inline, функции...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)