ошибка перегрузки функции: почему эти операторы конфликтуют? - PullRequest
1 голос
/ 17 октября 2008

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

Движок определяет класс vector3 как определение типа другого класса vector3 с операторами равенства, которые находятся в пространстве имен движка, а не в классе vector3. Я добавил класс в приложение, в котором также были операторы равенства в пространстве имен приложения.

Когда я попытался скомпилировать, несвязанные, но близкие сравнения с векторами не удалось, потому что он не смог найти подходящий оператор равенства. Я подозревал, что вызвал конфликт, поэтому переместил свои операторы равенства в добавленный класс, и компиляция прошла успешно.

// engine.h
namespace Engine
{
    class Vector3Impl { ... };
    typedef Vector3Impl Vector3;
    bool operator==(Vector3 const &lhs, Vector3 const &rhs) { ... }
}


// myfile.cpp
#include "engine.h"

namespace application
{
    class MyClass { ... };
    bool operator==(MyClass const &lhs, MyClass const &rhs) { ... }

    void myFunc(...)
    {
        if ( myClassA == myClassB ) { ... } // builds
    }

    void anotherFunc(...)
    {
        Engine::Vector3 a, b;
        ...
        if ( a == b ) { ... } // fails
    }
}

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

Я пытался воспроизвести эту ошибку в примере проекта на C ++, но он отказывается сломаться. Должно быть что-то в большой большой кодовой базе, которая вызывает эту проблему, но я не уверен, с чего начать. Что-то похожее на мошенническое "использование двигателя"? У кого-нибудь есть идеи?

Ответы [ 3 ]

2 голосов
/ 17 октября 2008

C ++ Standard, 3.4.4.2 объявляет:

Для каждого типа аргумента T в вызове функции существует набор из нуля или более связанных пространств имен и набор из нуля или более связанных классов, которые необходимо учитывать. Наборы пространств имен и классов полностью определяются типами аргументы функции (и пространство имен любого аргумента шаблона). Имена типов и объявления об использовании используется для указания типов, не участвующих в этом наборе .

ADL не работает с typedef.

0 голосов
/ 17 октября 2008

Однажды я столкнулся с той же проблемой с компилятором, который не имел Argument Dependent Lookup (Koenig Lookup - спасибо @igor) (VC6, я думаю). Это означает, что когда он видит оператора, он просто смотрит во вложенные пространства имен.

Так вы можете сказать нам, какой компилятор вы используете?

Переход к другому компилятору решил эту проблему.

Очень неудобно.

0 голосов
/ 17 октября 2008
bool operator==(Vector3 const &lhs, Vector3 const &rhs) { ... }

Каноническое определение оператора равенства, определенного в классе, должно иметь только один аргумент, а именно rhs. LHS это. Не знаю, будет ли это решением вашей проблемы.

Вот что я бы написал:

класс Vector3 { оператор bool == (const Vector3 & rhs) const {...} };

...