У меня есть следующий код, который генерируется автоматически:
#include <vector>
#include <algorithm>
namespace foo{
struct S{};
namespace inner{
bool operator==(const S&,const S&){return true;}
}
}
namespace bar{
void func();
}
Теперь я хочу найти в контейнере объект S, используя алгоритм find STL:
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
Однако я получаю эту ошибку:
/opt/compiler-explorer/gcc-8.3.0/include/c++/8.3.0/bits/predefined_ops.h:241:17:
error: no match for 'operator==' (operand types are 'foo::S' and 'const foo::S')
{ return *__it == _M_value; }
Даже после добавления using foo::inner::operator==; я получаю ту же ошибку:
void bar::func(){
using foo::inner::operator==;
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
Однако, когда я это делаю, это работает:
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find_if (v.begin(),v.end(),[s](foo::S e){
using foo::inner::operator==;
return s==e;
});
}
Мои два вопроса:
using)Редактировать:
Благодаря ответу Макса (https://stackoverflow.com/a/55517500/8900666) я нашел способ исправить эту проблему (немного некрасиво, но работает):
// Generated code
#include <vector>
#include <algorithm>
namespace foo{
struct S{};
namespace inner{
bool operator==(const S&,const S&){return true;}
}
}
namespace bar{
void func();
}
// My code
namespace foo{
using inner::operator==;
}
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
Я добавлю фрагмент с using для лучшего понимания
@LeonardoFaria - Спасибо!
добавил фрагмент (он предпоследний)
Первый случай не работает из-за ADL — компилятор ищет в пространстве имен foo, а не foo::inner для operator==. Добавьте using inner::operator== в пространство имен foo.





Проблема заключается в поиске, зависимом от аргумента (ADL).
Где-то внутри шаблона std::find есть if (*it == value), где value и it — зависимые типы. Это означает, что компилятор будет ждать создания экземпляра шаблона, чтобы найти правильный operator== для использования.
Но места, где он ищет operator==, более или менее ограничены (не вдаваясь слишком глубоко в детали поиска без уточнения имени):
Все окружающие пространства имен, но поиск здесь останавливается на поиске Любыеoperator==. (Не имеет значения для вас, но может сбить с толку людей, которые просто добавляют операторы, например, для объектов std в глобальное пространство имен, например, «поддержка» operator+ для std::vector).
Выполняется ADL — пространства имен объектов (откуда *it и *value) ищутся на соответствие operator==.
Но operator==, который вы хотите использовать, не может быть найден таким образом — он находится в другом (более глубоком) пространстве имен. В основном это ошибка в сгенерированном коде - операторы всегда должны находиться в том же пространстве имен, в котором определены объекты, с которыми они работают.
Итак, ответы:
Ваш operator== не найден, потому что он находится в неправильном пространстве имен.
Здесь нет проблем, потому что в лямбде найден правильный оператор, а std::find_if просто использует лямбду напрямую (без поиска вообще).
Но, безусловно, добавление оператора using добавит inner::operater== в глобальное пространство имен.
@MartinBonner В рамках того места, куда вы это поместили using. Именно поэтому работает второй случай. Но волшебным образом это не станет доступным для внутренностей std::find.
@LeonardoFaria Точно куда вы добавляете утверждение
using?