Ключевое слово c ++ friend означает больше, чем доступ к приватному? - PullRequest
0 голосов
/ 26 февраля 2019

Я написал простой класс и определил один конструктор копирования.Затем добавьте оператор сравнения друзей и сравните int с Int

template <class T>
class Int {
public:
    T value;
    Int(const T& value_) : value(value_) {
        ;
    }

    friend bool operator==(const Int<T>& f, const Int<T>& s) {
        return f.value == s.value;
    }
};

int main() {
    int a;
    Int<int> x(a);
    x == a;
}

Успешно скомпилировано.

Если я включу friend bool operator==(const Int<T>& f, const Int<T>& s); в шаблон, не являющийся другом.Я получаю сообщение об ошибке компилятора:

error: no match for 'operator==' (operand types are 'int' and 'Int<int>'
template <class T>
class Int {
public:
    T value;
    Int(const T& value_) : value(value_) {
        ;
    }
};

template <class T>
bool operator==(const Int<T>& f, const Int<T>& s) {
    return f.value == s.value;
}

int main() {
    int a;
    Int<int> x(a);
    x == a;
}

Означает ли это, что функции-друзья допускают определенные преобразования?

5 == x тоже работает.

1 Ответ

0 голосов
/ 27 февраля 2019

Значит ли ключевое слово 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 для автоматического «введения» этой бесплатной функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...