Значит ли ключевое слово c ++ friend больше, чем доступ к приватному?
В зависимости от контекста, это может иметь больше последствий, да.Например, встроенная функция friend
, не имеющая другого объявления, может быть найдена только путем поиска, зависящего от аргумента, даже если она является членом входящего в нее пространства имен:
namespace foo {
struct bar {
friend void baz(bar const&) {}
};
}
int main() {
foo::bar bar;
// foo::baz(bar); // ill-formed, no member baz in foo
baz(bar); // Okay, it *can* be found by ADL
};
Это не имеет прямого отношения ктвой вопрос, но вот так выглядит друг operator==
.И это сказал, что друг тоже не сам шаблон.Когда вы создаете экземпляр Int<int>
, это «внедряет» свободную функцию operator==
, которая, опять же, не шаблон, в пространство имен, членом которого является Int
.Когда эта операторная функция найдена (ADL) для целей x == a
, компилятор с радостью рассмотрит неявное преобразование a
в Int<int>
, потому что мы можем выполнять неявные преобразования для сопоставления с обычными свободными функциями.
И, говоря о преобразованиях ...
Я написал простой класс и определил один конструктор копирования.
Вы этого не сделали.Это пользовательский конструктор, принимающий аргумент int const&
, а не Int<int> const&
, как примет конструктор копирования.Вы определили конструктор преобразования (потому что он не явный), и именно так компилятор может преобразовать a
в Int<int>
выше.
Если я включу ...
В вашей второй версии оператором является шаблон.Это все еще ищется ADL.Но вычет аргументов шаблона учитывает только тип аргументов точный .То есть оба аргумента operator==
должны иметь возможность напрямую связываться с Int<T> const&
для некоторых T
.int
нельзя напрямую связать с Int<int> const&
, для этого требуется преобразование.Таким образом, он не соответствует виду аргумента, который шаблон должен использовать для вывода аргумента шаблона.Следовательно, шаблон не может быть создан и не является кандидатом.
Означает ли это, что функции друзей допускают определенные преобразования?
Нет, это не дружба.Это шаблон против не шаблонного бизнеса.Вы можете определить operator==
без дружбы, но это должно быть для каждого экземпляра Int
:
template <class T>
class Int {
public:
T value;
Int(const T& value_) : value(value_) {
;
}
};
bool operator==(const Int<int>& f, const Int<int>& s) {
return f.value == s.value;
}
Это также сделает ваш main
правильно сформированным.Но, как вы заметили, нецелесообразно объявлять их по отдельности, поэтому многие базы кода будут использовать версию friend
для автоматического «введения» этой бесплатной функции.