Оператор сравнения для std::vector<T> не может найти оператор сравнения для T
Следующий очень простой код не скомпилируется
#include <vector>
#include <string>
namespace Foobar {
struct Test {
std::string f;
std::uint16_t uuid;
};
}
bool operator==(const Foobar::Test& lhs, const Foobar::Test& rhs){
return lhs.f == rhs.f && lhs.uuid == rhs.uuid;
}
int main(){
std::vector<Foobar::Test> a;
std::vector<Foobar::Test> b;
if(a==b){
}
return 0;
}
Не будет компилироваться ни в один из моих компиляторов.
Хотя следующее
#include <vector>
#include <string>
namespace Foobar {
struct Test {
std::string f;
std::uint16_t uuid;
};
bool operator==(const Foobar::Test& lhs, const Foobar::Test& rhs){
return lhs.f == rhs.f && lhs.uuid == rhs.uuid;
}
}
int main(){
std::vector<Foobar::Test> a;
std::vector<Foobar::Test> b;
if(a==b){
}
return 0;
}
Компилирует просто отлично, что заставляет меня думать std::vector<T>
Оператор сравнения выглядит в пространстве имен T
почему он не учитывает глобальное пространство имен?
1 ответ
Обычный поиск безусловного имени начинает поиск в контексте, где используется имя, и идет вверх по цепочке окружающих областей. Он останавливается в самой вложенной области, содержащей соответствующее имя. Это верно даже в том случае, если найденное таким образом имя позднее будет признано непригодным (например, перегрузка функции нежизнеспособна для данного вызова или функция-член недоступна).
Здесь контекст поиска std::operator==(vector, vector)
поэтому он начинает искать в пространстве имен std
, Есть много перегрузок operator==
в пространстве имен std
таким образом, обычный поиск останавливается там и никогда не достигает глобального пространства имен.
Во втором примере перегрузка обнаруживается в зависимости от аргумента. Этот поиск выполняется специально для имен функций в вызовах функций, в дополнение к неквалифицированному поиску, и ищет имена в областях, связанных с типами аргументов вызова. В примере пространство имен Foobar
связан с Foobar::Test
и так, зависящий от аргумента поиск ищет это пространство имен и находит Foobar::operator==
,
По этой причине свободные функции, которые логически являются частью открытого интерфейса класса - например, перегруженные операторы, - должны обычно определяться в том же пространстве имен, что и сам класс, чтобы дать возможность зависимо-аргументному поиску работать. std::operator==(vector, vector)
хороший пример этого - a==b
в вашем примере работает через аргумент-зависимый поиск.