Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463

Friend declaration construction

16.07.2016, 04:27. Показов 3475. Ответов 36
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Читаю C++ Templates. The Complete Guide. Вандервурд, Джоссатис
В одной из глав речь идет об объявлениях дружественных конструкций.

Основная идея такова:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T1, typename T2>
void combine(T1, T2);
 
class Mixer
{
    friend void combine<>(int, int);
    friend void combine<int, int>(int, int);
    friend void combine<char>(char, int);
 
    // errors
    friend void combine<char>(char&, int);
    friend void combine<>(long, long) {  }
};
Можно объявить дружественной шаблон функции. Если можно вывести аргументы шаблона, угловые скобки могут быть пустыми.
Определение специализации шаблона запрещено.

Но говорится и о втором варианте объявления дружественных конструкций, в котором угловые скобки вообще опускаются.
В качестве пояснения, даются два правила:

1) Если имя не полное (без указания пространств имен или класса), то такое имя может ссылаться только на обычную функцию.
При этом, если в точке объявления функции в качестве дружественной она еще не была объявлена, то дружественная конструкция,
ее первое объявление, в таком случае оно может быть и определением.



2) Если имя полное (содержит :: ), то оно должно ссылаться на ранее объявленную функцию или шаблон функции.
Предпочтение отдается функции перед шаблоном функции. Не может быть определения.


Дается разъясняющий пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void multiply(void*);
 
template <typename T>
void multiply(T);
 
class Pride
{
public:
    friend void multiply(int) { }           /* имя не полное, может быть определением */
    friend void ::multiply(void*);        /* имя полное, ссылается на обычную функцию */
    friend void ::multiply(int);            /* имя полное, ссылается на шаблон функции для типа int */
    friend void ::multiply<double*>(double*); /* также могут быть и угловые скобки */
};
Проблема возникает для:

C++
1
    friend void ::multiply(int);  /* имя полное, ссылается на шаблон функции для типа int */
Если переписать этот пример вот так, для проверки дружественности специализации шаблона функции
multiply<int> классу Mixer:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void multiply(void*);
 
template <typename T>
void multiply(T);
 
class Pride
{
    int p;
public:
    friend void multiply(int) { }
    friend void ::multiply(void*);
    friend void ::multiply(int);
    friend void ::multiply<double*>(double*);
};
 
template <>
void multiply(double*)
{
    Pride pr;
    pr.p = 0; /* тут все нормально */
}
 
template <>
void multiply(int)
{
    Pride pr;
    pr.p = 0; /* а тут ошибка, то есть эта специализация не является дружественной */
}
Почему так?
Миниатюры
Friend declaration construction  
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.07.2016, 04:27
Ответы с готовыми решениями:

Ошибка E2238 Multiple declaration for и E2344 Earlier declaration of выпадает на одной и той же строке
Доброго всем времени суток. Помогите, пожалуйста решить вот такую проблему. На одну и ту же строку компилятор выдает 2 ошибки: ...

Ошибка: friend declaration declares a non-template function
Всем доброго времени суток! Я корплю над задачкой: нада сделать класс вектор шаблонным, перегрузить операции ввода-вывода, и тд и тп. ...

Почему friend ostrem& operator <<(ostream& outs, const Rational&); - invalid function declaration?
Пытаюсь скомпилировать программу пишет friend ostrem&amp; operator &lt;&lt;(ostream&amp; outs, const Rational&amp;); - invalid function declaration. ...

36
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
16.07.2016, 18:09
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Nosey Посмотреть сообщение
Ваш приведенный код попадает под первое правило, ибо
Тьфу, блин, действительно. Разница там между deducted и non-deducted.
Сейчас ухожу на пьянку. Вечером, если буду в состоянии, продемонстрирую разницу примером. Ну, или завтра, если буду не в состоянии.
0
16.07.2016, 18:44

Не по теме:

Цитата Сообщение от avgoor Посмотреть сообщение
продемонстрирую разницу примером
Лучше ссылочкой на стандарт, это будет вах какая конфетка.:)

0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
17.07.2016, 16:29
Я протрезвел, продолжим
Цитата Сообщение от Nosey Посмотреть сообщение
Лучше ссылочкой на стандарт, это будет вах какая конфетка.
Так вы ж сами ее привели! Впрочем, еще одна понадобится:
14.2 Names of template specializations
1 A template specialization (14.7) can be referred to by a template-id:
simple-template-id:
template-name<template-argument-list opt>
template-id:
simple-template-id
operator-function-id<template-argument-list opt>
...
Сперва приведу код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class A;
 
namespace Foo
{
    template<class T> void foo(A& a, T l, T r);
    void foo(A& a, int l, int r);
}
 
class A
{
    int a;
    friend void Foo::foo<int>(A&, int, int); // Friend declaration 1
    friend void Foo::foo(A&, int, int); // Friend declaration 2
};
 
namespace Foo
{
    template<class T>
    void foo(A& a, T l, T r)
    {
        a.a = l + r;
    }
    void foo(A& a, int l, int r)
    {
        a.a = l + r;
    }
}
 
int main()
{
    A a;
    Foo::foo(a, 1, 2); // Call 1
    Foo::foo<int>(a, 1, 2); // Call 2
}
Т.е. пункт 1:
— if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a
specialization of a function template, otherwise
относится к Friend declaration 1 (см. код) т.е. с явным указанием шаблона.

Второй и третий пункты:
— if the name of the friend is a qualified-id and a matching non-template function is found in the specified
class or namespace, the friend declaration refers to that function, otherwise,
— if the name of the friend is a qualified-id and a matching function template is found in the speci-
fied class or namespace, the friend declaration refers to the deduced specialization of that function
template (14.8.2.6), otherwise,
определяют последовательность, в которой ищутся имена, в случае если указано только имя (Friend declaration 2)
Тогда, если есть нешаблонная функция с таким именем - она друг. Потом ищется шаблон с таким именем. Если и он не найден - имя должно быть неквалифицированным, и оно объявляется/определяется во внешнем неймспейсе.

Соответственно: Friend declaration 2 - относится к void foo(), а если ее закомментировать - будет относится к void foo<int>(). Как-то так.
1
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
17.07.2016, 17:39
avgoor, Так-то оно так, но вопрос в следующем коде:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
 
class A;
 
namespace Foo
{
    template<class T> void foo(A& a, T l, T r);
}
 
class A
{
    int a;
    friend void Foo::foo(A&, int, int); // По стандарту этот код должен работать, а работает только в студии.
//    friend void Foo::foo<>(A&, int, int); // А работает кросплатформенно только этот.
};
 
namespace Foo
{
    template<>
    void foo<int>(A& a, int l, int r)
    {
        a.a = l + r;
    }
}
 
int main()
{
    A a;
    Foo::foo(a, 1, 2); // Call 1
}
1
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
17.07.2016, 18:37
Цитата Сообщение от Nosey Посмотреть сообщение
По стандарту этот код должен работать, а работает только в студии.
Пичалька
0
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
17.07.2016, 18:40  [ТС]
Nosey, так вроде ссылка на статью с авторством Герба Саттера, которую Вы скинули как раз объясняет эти моменты? )) Разве нет? ) Саттер пишет, что это баг и правило #3 следует избегать. Лучше использовать #1, там где qualified or unqualified template-id указывается.
1
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
17.07.2016, 19:09
Цитата Сообщение от ASCII Посмотреть сообщение
Разве нет?
Саттер писал что в 2002 году ни одно правило кросскомпиляторно не работало, теперь первое фурычит, еще 15 лет и 3-е тоже заработает
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
17.07.2016, 19:24
кароче! вы одолели уже!
напишите код,
который иллюстрирует все три правила.

по мне так, 3-е правило нефига не работает,
причем во всех топовых компиляторах

я понимаю - есть обходной путь.

но блин, это не суть.

суть в том, что бы понять значение всех этих правил.

вот давайте с толком, с расстановкой, и по-русски.
с примерами кода.

а потом модераторы вынесут эту жемчужину в шапку раздела.

это реально интересный момент языка.
1
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
17.07.2016, 19:50
Цитата Сообщение от hoggy Посмотреть сообщение
напишите код,
который иллюстрирует все три правила.
Цитата Сообщение от hoggy Посмотреть сообщение
который иллюстрирует все три правила.
You are welcome :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
 
class A;
 
template<typename T> void f1(A& a, T v);
template<typename T> void f1_1(A& a, T v);
template<typename T> void f3(A& a, T v);
void f2(A& a, int v);
 
class A
{
    int a;
    friend void ::f1<>(A&, int); // первое правило - привязывает к шаблонам
    friend void f1_1<>(A&, int); // также первое правило - привязывает к шаблонам, т.е квалификация не обязательна.
    friend void ::f2(A&, int); // второе правило - привязывает к обычным функциям
    friend void ::f3(A&, int); // третье правило - если (2)-ой вариант не сработал - обязаны попытаться привязать к шаблону. Юзая классическую дедукцию аргументов шаблона.
    friend void f4(A&, int); // четвертое правило - компилятор сам объявит эту функцию.
};
 
template<>
void f1<int>(A& a, int v)
{
    a.a = v;
    std::cout << a.a;
}
 
template<>
void f1_1<int>(A& a, int v)
{
    a.a = v;
    std::cout << a.a;
}
 
void f2(A& a, int v)
{
    a.a = v;
    std::cout << a.a;
}
 
template<>
void f3<int>(A& a, int v)
{
    a.a = v;
    std::cout << a.a;
}
 
void f4(A& a, int v)
{
    a.a = v;
    std::cout << a.a;
}
 
int main()
{
    A a;
    f1(a,10);
    f1_1(a,11);
    f2(a,12);
    f3(a,13);
    f4(a,14);
}
В студии верхний код соберется. В остальных компиляторах мне лень дотошно разбираться и описывать, но вот пока баловался понял, что в gcc - багов по теме дружественности больше, чем просто "не привязывает дружественность"
3
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
17.07.2016, 20:15  [ТС]
Nosey, наверное стоит дополнить, что friend declaration для f3,то есть то самое третье правило, как раз оно и является багом в каких-то компиляторах
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
17.07.2016, 20:35
Цитата Сообщение от Nosey Посмотреть сообщение
You are welcome :
эта тема уйдет в бездну.
но этот материал реально важен, я считаю.
я за то, что бы модераторы прикрепили его к разделу.

давайте назовем раздел "стандарт с++ по-русски"

я за то, что бы этот опыт не канул в лету.


если вы согласны: пишите "TODO:раздел для стантарта"

а потом по этим тегам можно будет найти все сообщения,
и убедиться, что это интересно людям.

Добавлено через 14 минут
ASCII, я вашими спасибками Индустрию не накормлю.
вы затронули интересную тему,
о которой многие даже не задумывались.

теперь давайте закрепим результат - тодокайте!

пишите: TODO:"стандарт с++ по-русски"

пусть модераторы создадут площадку для трактовки стандарта,
и поместят туда эту тему.


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

а потом в этом разделе смогут появляться самые разные другие трактовки.

это круто для холиварных воийн местных военов

как вы считаете?
4
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
17.07.2016, 20:44

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
теперь давайте закрепим результат - тодокайте!
Вы желаете загадить тему, тудушками? :)
TODO:раздел для стантарта



А вообще, я конечно за тему, со списком обсужденных нюансов стандарта.
0
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
17.07.2016, 20:56  [ТС]
Nosey, а я вообще хотел переводить разделы стандарта и создать тему, со ссылками на каждый перевод по конкретной теме с подробными примерами кода в качестве пояснений. Хотя это наверное утопия.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
17.07.2016, 21:08
круто, парни!
я создал тему, что бы привлечь внимание администрации.
я тоже хотел бы приложить свои ручонки к теме трактовок стандарта.
0
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
17.07.2016, 21:52  [ТС]
hoggy, дай знать, когда ответят. Вообще я поддерживаю идею русификации стандарта. То есть чуть чуть очеловечить изложение в стандарте. Плюс выявление багов всяких (как отдельную тему).
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
17.07.2016, 21:58
Цитата Сообщение от ASCII Посмотреть сообщение
дай знать, когда ответят.
собирайте лайки-подписи:
https://www.cyberforum.ru/cpp/thread1781988.html
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
28.02.2017, 16:40
hoggy, круто что нашел подобную тему...в инете такой инфы почти нет
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.02.2017, 16:40

Перегрузка операторов, friend или нет friend?
Всем здравствуйте. Есть такой вопрос: при перегрузке операторов в классе(пусть будут + и = (вообще неважно, за исключением потока)) как и...

Friend для friend
всем доброго времени суток, покажу проблему на примере: Class B; class A{ int F; friend B; public: A(){F=0;}; };

[DCC Error] E2037 Declaration of 'SelectFitFromObzor' differs from previous declaration
Приветствую всех! Возникла проблема, уже всё перепробовал, даже методом тыка! Вот код: unit ufmCoLiTecLight; interface

Ошибка Declaration of 'Button1' differs from previous declaration
Помогите, пожалуйста, исправить ошибку: Declaration of 'Button1' differs from previous declaration unit Unit1; interface ...

Ошибка: declaration of 'Init' differs from previous declaration
В низу где procedure procedure TDot.Init(X0,Y0,R0:Integer;Cr:COLORREF); ошибка declaration of 'Init' differs from previous declaration...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru