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

Friend declaration construction

16.07.2016, 04:27. Показов 3261. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Новости компьютерного мира и их обсуждение (4) Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru