Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
#1

Friend declaration construction - C++

16.07.2016, 04:27. Просмотров 946. Ответов 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  
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2016, 04:27     Friend declaration construction
Посмотрите здесь:

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

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

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

Класс friend - C++
Проблемка с доступом через дружественный класс: class Game { friend Player; //тут объявлен класс-друг ...

Не работает friend - C++
#ifndef INTEGERLONGS_HPP_INCLUDED #define INTEGERLONGS_HPP_INCLUDED...

friend function - C++
Помогите плз разобраться: Когда я делаю инкремент &quot;х&quot; через закрытые функции класса - все работает нормально, а когда через...

friend function - C++
После добавления дружественной ф-ции sum( а она для сложения salary у человека, которого я выберу) класс перестал работать. Что у меня не...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
avgoor
884 / 519 / 112
Регистрация: 05.12.2015
Сообщений: 1,464
16.07.2016, 18:09     Friend declaration construction #21
Цитата Сообщение от Nosey Посмотреть сообщение
Ваш приведенный код попадает под первое правило, ибо
Тьфу, блин, действительно. Разница там между deducted и non-deducted.
Сейчас ухожу на пьянку. Вечером, если буду в состоянии, продемонстрирую разницу примером. Ну, или завтра, если буду не в состоянии.
Nosey
16.07.2016, 18:44
  #22

Не по теме:

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

avgoor
884 / 519 / 112
Регистрация: 05.12.2015
Сообщений: 1,464
17.07.2016, 16:29     Friend declaration construction #23
Я протрезвел, продолжим
Цитата Сообщение от 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>(). Как-то так.
Nosey
1344 / 395 / 107
Регистрация: 22.10.2014
Сообщений: 860
Завершенные тесты: 2
17.07.2016, 17:39     Friend declaration construction #24
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
}
avgoor
884 / 519 / 112
Регистрация: 05.12.2015
Сообщений: 1,464
17.07.2016, 18:37     Friend declaration construction #25
Цитата Сообщение от Nosey Посмотреть сообщение
По стандарту этот код должен работать, а работает только в студии.
Пичалька
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
17.07.2016, 18:40  [ТС]     Friend declaration construction #26
Nosey, так вроде ссылка на статью с авторством Герба Саттера, которую Вы скинули как раз объясняет эти моменты? )) Разве нет? ) Саттер пишет, что это баг и правило #3 следует избегать. Лучше использовать #1, там где qualified or unqualified template-id указывается.
Nosey
1344 / 395 / 107
Регистрация: 22.10.2014
Сообщений: 860
Завершенные тесты: 2
17.07.2016, 19:09     Friend declaration construction #27
Цитата Сообщение от ASCII Посмотреть сообщение
Разве нет?
Саттер писал что в 2002 году ни одно правило кросскомпиляторно не работало, теперь первое фурычит, еще 15 лет и 3-е тоже заработает
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
17.07.2016, 19:24     Friend declaration construction #28
кароче! вы одолели уже!
напишите код,
который иллюстрирует все три правила.

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

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

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

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

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

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

это реально интересный момент языка.
Nosey
1344 / 395 / 107
Регистрация: 22.10.2014
Сообщений: 860
Завершенные тесты: 2
17.07.2016, 19:50     Friend declaration construction #29
Цитата Сообщение от 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 - багов по теме дружественности больше, чем просто "не привязывает дружественность"
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
17.07.2016, 20:15  [ТС]     Friend declaration construction #30
Nosey, наверное стоит дополнить, что friend declaration для f3,то есть то самое третье правило, как раз оно и является багом в каких-то компиляторах
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
17.07.2016, 20:35     Friend declaration construction #31
Цитата Сообщение от Nosey Посмотреть сообщение
You are welcome :
эта тема уйдет в бездну.
но этот материал реально важен, я считаю.
я за то, что бы модераторы прикрепили его к разделу.

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

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


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

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

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

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

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

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


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

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

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

как вы считаете?
Nosey
1344 / 395 / 107
Регистрация: 22.10.2014
Сообщений: 860
Завершенные тесты: 2
17.07.2016, 20:44     Friend declaration construction #32

Не по теме:

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



А вообще, я конечно за тему, со списком обсужденных нюансов стандарта.
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
17.07.2016, 20:56  [ТС]     Friend declaration construction #33
Nosey, а я вообще хотел переводить разделы стандарта и создать тему, со ссылками на каждый перевод по конкретной теме с подробными примерами кода в качестве пояснений. Хотя это наверное утопия.
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
17.07.2016, 21:08     Friend declaration construction #34
круто, парни!
я создал тему, что бы привлечь внимание администрации.
я тоже хотел бы приложить свои ручонки к теме трактовок стандарта.
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
17.07.2016, 21:52  [ТС]     Friend declaration construction #35
hoggy, дай знать, когда ответят. Вообще я поддерживаю идею русификации стандарта. То есть чуть чуть очеловечить изложение в стандарте. Плюс выявление багов всяких (как отдельную тему).
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
17.07.2016, 21:58     Friend declaration construction #36
Цитата Сообщение от ASCII Посмотреть сообщение
дай знать, когда ответят.
собирайте лайки-подписи:
http://www.cyberforum.ru/cpp/thread1781988.html
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.02.2017, 16:40     Friend declaration construction
Еще ссылки по теме:

Friend Function - C++
Я не очень понимаю как пользаватса Friend функцыей Class.h #include &lt;stdio.h&gt; #include &quot;iostream&quot; using namespace std; ...

friend классы - C++
Доброго времени суток форумчани. Вот потихоньку учу C++, добрался до дружественных функций и классов. Вроде бы все ясно, но все равно не...

класс Friend - C++
Подскажите в каких случаях лучше использовать класс friend? Известно что класс friend нарушает принцип инкапсуляции, так почему же мы его...

Friend и Static - C++ Builder
Здравсвуйте программисты! Изучаю про классы. В теме из книги встречаются постоянно операторы friend и static . Подскажите пожалуйста,как...

Friend класса - C++
#include &lt;iostream&gt; class assoc { struct pair { char* name; int val; }; int free;


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

Или воспользуйтесь поиском по форуму:
zarko97
251 / 32 / 0
Регистрация: 11.10.2015
Сообщений: 243
28.02.2017, 16:40     Friend declaration construction #37
hoggy, круто что нашел подобную тему...в инете такой инфы почти нет
Yandex
Объявления
28.02.2017, 16:40     Friend declaration construction
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru