Оператора перегрузка
От: Barbar1an Украина  
Дата: 10.03.19 14:14
Оценка:
template<class T> struct CObject
{
    CNexusObject *    Object = nullptr;

    CObject(){}
    CObject(CNexusObject * o) : Object(o)
    {
    }

    bool operator == (const CNexusObject * o) const 
    {
        return Object && Object == o;
    }

    T * operator->()
    {
        return dynamic_cast<T *>(Object);
    }

    operator T * () const
    {
        return dynamic_cast<T *>(Object);
    }
};

int main()
{
    CObject<CNexusObject> a;
    CNexusObject * b = nullptr;

            
    if(a == b)   // нужно чтобы вызывался мой оператор ==, вместо этого: error C2666: 'CObject<CNexusObject>::operator ==': 2 overloads have similar conversions
    {
    }
}



как разрулить?
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Оператора перегрузка
От: Muxa  
Дата: 10.03.19 14:58
Оценка:
B>как разрулить?
if(a.operator ==(b))
Re: Оператора перегрузка
От: rg45 СССР  
Дата: 10.03.19 15:17
Оценка: +1 :)
Здравствуйте, Barbar1an, Вы писали:

  ccode
B>
B>template<class T> struct CObject
B>{
B>    CNexusObject *    Object = nullptr;

B>    CObject(){}
B>    CObject(CNexusObject * o) : Object(o)
B>    {
B>    }

B>    bool operator == (const CNexusObject * o) const 
B>    {
B>        return Object && Object == o;
B>    }

B>    T * operator->()
B>    {
B>        return dynamic_cast<T *>(Object);
B>    }

B>    operator T * () const
B>    {
B>        return dynamic_cast<T *>(Object);
B>    }
B>};

B>int main()
B>{
B>    CObject<CNexusObject> a;
B>    CNexusObject * b = nullptr;

            
B>    if(a == b)   // нужно чтобы вызывался мой оператор ==, вместо этого: error C2666: 'CObject<CNexusObject>::operator ==': 2 overloads have similar conversions
B>    {
B>    }
B>}
B>


B>как разрулить?


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

Кроме того, хотелось бы обратить внимание на некоторые не очень хорошие моменты в коде: неявный преобразующий конструктор, неявный оператор преобразования к сырому указателю, открытый доступ к членам-данным. Ну и совсем мелочь — стиль именования членов-данных, затрудняющий чтение кода.

После исправления перечисленного, код мог бы выглядеть как-то так:

https://ideone.com/teMaOi

#include <iostream>
#include <cassert>

template<class T>
class CObject
{
private:
    T* m_Object = nullptr;

public:

    CObject() = default;
    explicit CObject(T* o) : m_Object(o) {  }

    T* get() const { return m_Object; }

    explicit operator bool() const { return m_Object != nullptr; }
    T* operator->() const { assert(m_Object); return m_Object; }
    T& operator* () const { assert(m_Object); return *m_Object; }
};

template <typename T>
bool operator == (const CObject<T>& lhs, const CObject<T>& rhs) { return lhs.get() == rhs.get(); }

template <typename T>
bool operator == (T* lhs, const CObject<T>& rhs) { return lhs == rhs.get(); }

template <typename T>
bool operator == (const CObject<T>& lhs, T* rhs) { return lhs.get() == rhs; }

template <typename T>
bool operator != (const CObject<T>& lhs, const CObject<T>& rhs) { return lhs.get() != rhs.get(); }

template <typename T>
bool operator != (T* lhs, const CObject<T>& rhs) { return lhs != rhs.get(); }

template <typename T>
bool operator != (const CObject<T>& lhs, T* rhs) { return lhs.get() != rhs; }

int main()
{
    class CNexusObject;

    CObject<CNexusObject> a;
    CNexusObject * b = nullptr;

    if(a == b)
    {
        std::cout << "Well done!" << std::endl;
    }
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.03.2019 15:34 rg45 . Предыдущая версия .
Re: Оператора перегрузка
От: LaptevVV Россия  
Дата: 10.03.19 15:21
Оценка:
Здравствуйте, Barbar1an, Вы писали:

B>

B>int main()
B>{
B>    CObject<CNexusObject> a;
B>    CNexusObject * b = nullptr;
   
B>    if(a == b)   // error C2666: 'CObject<CNexusObject>::operator ==': 2 overloads have similar conversions
B>    {
B>    }
B>}
B>

Оба твоих объекта — не константные.
А между тем, и метод у тебя константный, и параметр — константа.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Оператора перегрузка
От: rg45 СССР  
Дата: 10.03.19 15:27
Оценка: +2
Здравствуйте, LaptevVV, Вы писали:

  ccode
B>>

B>>int main()
B>>{
B>>    CObject<CNexusObject> a;
B>>    CNexusObject * b = nullptr;
   
B>>    if(a == b)   // error C2666: 'CObject<CNexusObject>::operator ==': 2 overloads have similar conversions
B>>    {
B>>    }
B>>}
B>>


LVV>Оба твоих объекта — не константные.

LVV>А между тем, и метод у тебя константный, и параметр — константа.

Константные методы можно вызывать для неконстантных объектов — наоборот нельзя.

У него ведь проблема не в константности, а в неоднозначности — рассматриваемое сравнение можно выполнить двумя равноценными способами:
1) применить оператор сравнения, определенный в классе;
2) применить оператор неявного преобразования, после чего сравнить сырые указатели.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.03.2019 15:47 rg45 . Предыдущая версия . Еще …
Отредактировано 10.03.2019 15:31 rg45 . Предыдущая версия .
Re[3]: Оператора перегрузка
От: Barbar1an Украина  
Дата: 10.03.19 16:50
Оценка:
Здравствуйте, rg45, Вы писали:

R>У него ведь проблема не в константности, а в неоднозначности — рассматриваемое сравнение можно выполнить двумя равноценными способами:

R>1) применить оператор сравнения, определенный в классе;
R>2) применить оператор неявного преобразования, после чего сравнить сырые указатели.

а почему явный оператор не имеет приоритета? вроде логично
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[2]: Оператора перегрузка
От: Barbar1an Украина  
Дата: 10.03.19 16:57
Оценка: :))
Здравствуйте, rg45, Вы писали:

R>Кроме того, хотелось бы обратить внимание на некоторые не очень хорошие моменты в коде: неявный преобразующий конструктор, неявный оператор преобразования к сырому указателю, открытый доступ к членам-данным. Ну и совсем мелочь — стиль именования членов-данных, затрудняющий чтение кода.


это всё хорошо, но это хорошо работает когда вам платят за время а не вы платите
к тому же 100500 get'ов в коде и явные касты там где и без них можно тоже читабельности не добавляют

что читатабельнее?


a == b 
или
a.get() == (CObject *)b

Core->Manager
или
m_core.get()->get_manager()


у меня в таким стиле проекту уже 10 лет и никаких проблем о которых говорят теоретики у меня так и не возникло, например паблик мемберы никогда не создавали проблем изза своей публичности
и консты везде подряд тоже не нужны, такой стиль(перестраховка везде и всюду) нужен тока если у вас в команде индусы которые не могут понять, принять и следовать принятой идеологии, и их нада как детей от всего ограждать
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Отредактировано 10.03.2019 17:02 Barbar1an . Предыдущая версия . Еще …
Отредактировано 10.03.2019 17:01 Barbar1an . Предыдущая версия .
Отредактировано 10.03.2019 16:58 Barbar1an . Предыдущая версия .
Re[3]: Оператора перегрузка
От: rg45 СССР  
Дата: 10.03.19 17:31
Оценка:
Здравствуйте, Barbar1an, Вы писали:

B>это всё хорошо, но это хорошо работает когда вам платят за время а не вы платите

B>к тому же 100500 get'ов в коде и явные касты там где и без них можно тоже читабельности не добавляют

B>что читатабельнее?


B>

B>a == b 
B>или
B>a.get() == (CObject *)b

Core->>Manager
B>или
B>m_core.get()->get_manager()
B>


Ну ты мой пример-то хоть посмотри. Где ты там видишь что-нибудь похожее на "a.get() == (CObject *)b"? Использование же осталось в точности как ты хочешь:

    if(a == b)
    {
        std::cout << "Well done!" << std::endl;
    }
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.03.2019 18:11 rg45 . Предыдущая версия . Еще …
Отредактировано 10.03.2019 17:43 rg45 . Предыдущая версия .
Отредактировано 10.03.2019 17:42 rg45 . Предыдущая версия .
Отредактировано 10.03.2019 17:32 rg45 . Предыдущая версия .
Re[4]: Оператора перегрузка
От: Muxa  
Дата: 10.03.19 17:57
Оценка:
B>а почему явный оператор не имеет приоритета? вроде логично
Может потому что явного каста нет.
Re[4]: Оператора перегрузка
От: rg45 СССР  
Дата: 10.03.19 18:08
Оценка:
Здравствуйте, Barbar1an, Вы писали:

R>>У него ведь проблема не в константности, а в неоднозначности — рассматриваемое сравнение можно выполнить двумя равноценными способами:

R>>1) применить оператор сравнения, определенный в классе;
R>>2) применить оператор неявного преобразования, после чего сравнить сырые указатели.

B>а почему явный оператор не имеет приоритета? вроде логичноё


Я не знаю, на чем основаны твои ожидания, но о том, что неявные преобразования это зло, не говорил только ленивый за последние лет 20. И твой пример — еще одно подтверждение этому. Можешь посмотреть, например, это: C++ Coding Standards. 101 Rules, Guidelines, and Best Practices, рекомендация №40: "Avoid providing implicit conversions".
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Оператора перегрузка
От: B0FEE664  
Дата: 10.03.19 21:39
Оценка:
Здравствуйте, Barbar1an, Вы писали:

B>что читатабельнее?

B>
B>a == b 
B>или
B>a.get() == (CObject *)b
B>


Barbar1an, согласно вашему коду a == b и a.get() == (CObject *)b имеют разную семантику.
И каждый день — без права на ошибку...
Re[2]: Оператора перегрузка
От: B0FEE664  
Дата: 10.03.19 21:42
Оценка: +1 :)
Здравствуйте, rg45, Вы писали:

R>Кроме того, хотелось бы обратить внимание на некоторые не очень хорошие моменты в коде: неявный преобразующий конструктор, неявный оператор преобразования к сырому указателю, открытый доступ к членам-данным. Ну и совсем мелочь — стиль именования членов-данных, затрудняющий чтение кода.


rg45, вы не заметили главного. Для кода
CObject<CNexusObject> a;
CNexusObject * b = nullptr;

условие
if(a == b)   
{
}

никогда не выполняется
Ибо, согласно логике Barbar1an, нулевой указатель нулевому указателю не равен.
И каждый день — без права на ошибку...
Re[3]: Оператора перегрузка
От: rg45 СССР  
Дата: 10.03.19 22:25
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>rg45, вы не заметили главного. Для кода

BFE>никогда не выполняется
BFE>Ибо, согласно логике Barbar1an, нулевой указатель нулевому указателю не равен.

Ну почему же, я заметил. Просто, даже включив все свое воображение, иначе, чем ошибку я это расценивать не могу. Причем, ошибку настолько не интересную, что даже не хочется заострять на ней внимание.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.03.2019 22:28 rg45 . Предыдущая версия .
Re: Оператора перегрузка
От: KOLRH Финляндия  
Дата: 11.03.19 06:29
Оценка:
Здравствуйте, Barbar1an, Вы писали:

jdoodle.com даёт подсказку:

note: candidate 1: 'bool CObject<T>::operator==(const CNexusObject*) const [with T = CNexusObject]'
bool operator == (const CNexusObject * o) const
^~~~~~~~
note: candidate 2: 'operator==(CNexusObject*, CNexusObject*)' <built-in>
if(a == b)
^

Получается ведь, что operator T * () const возвращает пойнтер на CNexusObject, и отсюда проблема с выбором operator ==.
Я бы предложил, что каждый объект должен сравнивать сам себя и убрал бы operator == из CObject и определил бы его в CNexusObject.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.