Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
#1

Шаблоны. Плохо понимаемые моменты из книги "Шаблоны С++. Справочник разработчика". (Вандевурд, Джосаттис) - C++

07.10.2015, 15:04. Просмотров 1868. Ответов 32
Метки нет (Все метки)

Так как изучаю эту книгу, то в некоторых местах возникают вопросы. Чтобы не плодить много тем, корни у которых одни, решил создать эту тему.

Дошел до места. Параметры шаблонов функций, не являющиеся типами.
Там описан такого вида пример
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <algorithm>
 
template <typename T, int VAL>
T addValue(T const& x){
   return x+VAL;
}
 
int main()
{
     vector<int> v1(100);
     vector<int> v2(100);
     transform(v1.begin(), v1.end(),v2.begin(),addValue<int,5>);
}
Дальше авторы уточняют о проблеме, которая проявляется в этом примере.
Заметим, что в этом примере проявляется следующая проблема: addValue<int, 5> — это шаблон функции, который интерпретируется как имя семейства перегруженных функций (даже если это семейство состоит всего из одного элемента).
Я вообще авторов не понял. Просьба прояснить этот туманный момент.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.10.2015, 15:04
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Шаблоны. Плохо понимаемые моменты из книги "Шаблоны С++. Справочник разработчика". (Вандевурд, Джосаттис) (C++):

Шаблоны класса:Матрица. Ошибка бинарный "=": не найден оператор, принимающий правый операнд типа "Matr<T>"
Выдает ошибку &quot;бинарный &quot;=&quot;: не найден оператор, принимающий правый операнд...

Помогите придумать несложную задачку по теме "Шаблоны классов"
Привет всем, я новичок в С++, и хочу сделать какую нибудь задачу по теме...

Реализовать шаблонный класс "Матрица" (шаблоны классов и функций)
Написать код программы на С++ Разработать шаблонные функции и классы. класс...

Шаблоны, ошибка "неоднозначный вызов перегруженной функции"
#include &lt;iostream&gt; using namespace std; void CheckInput(int &amp;); void...

Шаблоны. Ошибка компиляции: "Не удается сопоставить определение функции существующему объявлению"
vector.h #pragma once #ifndef _VECTOR_H #define _VECTOR_H #include...

Шаблоны С++. Класс "Квадратная матрица"
Здравствуйте, уважаемые программисты. Искренне прощу вашей помощи в решении...

32
ture
528 / 336 / 206
Регистрация: 27.11.2014
Сообщений: 1,043
07.10.2015, 15:17 #2
daslex, шаблон - это просто заготовка. шаблона не переживет компиляцию. на основе шаблона компилятор (вместо тебя) напишет конечную функцию с вполне конкретными типами. ты делаешь шаблон, что не писать сто раз одну и ту же функцию меня тип параметра.

Добавлено через 1 минуту
правда после этого набора слов препод у меня на уроке махнул рукой и отпустил всех пораньше.
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 15:18  [ТС] #3
Это не пояснение цитаты. Я знаю, что такое шаблон. Вопрос не в том, что он такое. Откуда тут интерпретация как семейства перегруженных функций.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 15:20 #4
А то, что он дальше пишет, почему не привёл? Там же объясняется причина.
0
ture
528 / 336 / 206
Регистрация: 27.11.2014
Сообщений: 1,043
07.10.2015, 15:21 #5
Ну это автор конечно завернул. Перегруженные они лишь пока не компилировалось. А потом все разные станут (трансляция имен с параметрами какая-то).
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 15:28 #6
Там сказано:
However, according to the current standard, sets of overloaded functions cannot be used for template parameter deduction. Thus, you have to cast to the exact type of the function template argument:

C++
1
2
3
std::transform (source.begin(), source.end(),  // start and end of source 
                dest.begin(),                  // start of destination 
                (int(*)(int const&)) addValue<int,5>);  // operation
There is a proposal for the standard to fix this behavior so that the cast isn't necessary in this context (see [CoreIssue115] for details), but until then the cast may be necessary to be portable.

Книжка 2002 года, может это уже не актуально.
1
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 15:29  [ТС] #7
Цитата Сообщение от nmcf Посмотреть сообщение
А то, что он дальше пишет, почему не привёл? Там же объясняется причина.
нет. там пишет про то, что "не по фэншую" и "как по фэншую".
В той книге, что у меня перед глазами причина не объясняется.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 15:32 #8
Я же привёл текст. Он говорит, что according to the current standard надо делать так-то. Но есть предложение стандарт подправить. Книжка древняя, может в C++11 уже не так. Пусть спецы прокомментируют.
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 15:36  [ТС] #9
Понимание первопричины гораздо важнее понимания отдельного кусочка. Да, он говорит как надо делать. Но тут я могу сделать, а где-то могу не сделать, ибо не вижу где и когда получится семейство перегруженных функций, а где семейства перегруженных функций не получится.
Я например, могу так понять, что если в параметрах шаблона функции есть хотя бы 1 не тип, то нужно явное приведение при обращении к такой функции. Но это может оказаться неправильным выводом, я просто конкретики не вижу. А полагаться на свои незнания как на знания нехорошо.
0
ture
528 / 336 / 206
Регистрация: 27.11.2014
Сообщений: 1,043
07.10.2015, 15:42 #10
C++
1
addValue<int, 5>
Это явное требование создать функцию для int и тут вызвать именно ее.

Добавлено через 6 минут
C++
1
int VAL
По моим понятиям транслируется в еще один параметр.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 15:46 #11
Лучший ответ Сообщение было отмечено daslex как решение

Решение

Цитата Сообщение от daslex Посмотреть сообщение
если в параметрах шаблона функции есть хотя бы 1 не тип, то нужно явное приведение при обращении к такой функции
Я из текста понял, что дело не в том, что там "не тип", а в самой записи. Она интерпретируется как шаблон.
1
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 15:50  [ТС] #12
Да. Интерпретируется как шаблон. А все. Понял
Там раньше написано
шаблон функции представляет семейство функций.
.

Не по теме:

Поназаводили синонимов, блин

. Вопрос отпал.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 15:52 #13
daslex, так в твоей книги есть перевод этого куска или нет?
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 16:00  [ТС] #14
Да. у меня русский вариант книги. Просто это за 30 страниц до написано.

Добавлено через 6 минут
(int(*)(int const&))addValue<int,5>);
Цитата Сообщение от nmcf Посмотреть сообщение
Книжка 2002 года, может это уже не актуально.
мне это тоже интересно узнать. актуально или же нет.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
07.10.2015, 16:57 #15
Что-то спецы пропали все.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
07.10.2015, 20:25 #16
daslex,
Вот эта надпись
Заметим, что в этом примере проявляется следующая проблема: addValue<int, 5> — это шаблон функции, который интерпретируется как имя семейства перегруженных функций (даже если это семейство состоит всего из одного элемента).
означает, что функция не интерпретируется однозначно, так, как будто бы речь идет о семействе перегруженных функций.
Семейство перегруженных функций - это когда вот так:
C++
1
2
int addValue(int a);
double addValue(double a);
Демо

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <vector>
#include <algorithm>
 
int addValue(int a);
double addValue(double a);
 
int main()
{
    std::vector<int> v1(100);
    std::vector<int> v2(100);
    std::transform(v1.begin(), v1.end(),v2.begin(),addValue);
}
http://rextester.com/QRA5825

В тот момент, когда мы попытаемся такую функцию передать в тот же std::transform, возникнет неоднозначность.
Так вот, Йосуттис и еще несколько человек в 1999 году нашли баг в формулировке стандарта. Вследствие этого бага, стандарт обозначал такое же поведение для шаблонной функции, не смотря на полную конкретизацию типов аргументов шаблона, он ее считал неоднозначной и компилятор, строго следовавший стандарту, выдавал ошибку. Лечилось это приведением типа (как сейчас лечится вариант с перегрузкой).

В книге есть сноска на обсуждение этого бага.
Issue 115.
Другое, на эту же тему: Issue 250.
Естественно, далеко не все компиляторы реализовали у себя это ошибочное требование, поэтому даже в то время подобная проблема проявлялась далеко не везде. Но я отлично помню эту проблему на GCC 2.x.
8
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
07.10.2015, 20:43  [ТС] #17
Насчет демо я понимаю и понял бы. Просто туманностей нагоняет такой момент, что в случае, описываемом в книге, у шаблона указано 2 параметра, тип которых известен. В демо же вариант более очевиден и просто показана неоднозначность непосредственно при самой перегрузке.
Я вообще сейчас так воспринимаю, что у transform возвращается значение, вот тип этого возвращаемого значения не может быть выведен шаблоном, потому что вызов функции по синтаксису как синтаксис имени, а не как синтаксис вызова.

Вот такой туман у меня в голове.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
07.10.2015, 20:59 #18
Лучший ответ Сообщение было отмечено daslex как решение

Решение

Цитата Сообщение от daslex Посмотреть сообщение
Я вообще сейчас так воспринимаю, что у transform возвращается значение, вот тип этого возвращаемого значения не может быть выведен шаблоном, потому что вызов функции по синтаксису как синтаксис имени, а не как синтаксис вызова.
Ничего не понял.
Суть в том, что transform (transform - шаблонная функция) принимает предикат, тип которого выводится из переданного параметра. Но предикат нельзя вывести однозначно, потому что вариантов больше, чем один. Такая же ситуация возникает, если мы подставим неполностью специфицированный шаблон, т.к. он воспримется как семейство функций.
C++
1
2
3
4
5
6
7
8
9
10
11
12
template <typename T, int V>
T addValue(int a)
{
    return a + V;
}
 
int main()
{
    std::vector<int> v1(100);
    std::vector<int> v2(100);
    std::transform(v1.begin(), v1.end(),v2.begin(), addValue<int>);
}
А вот баг заключался в том, что даже полностью специфицированный шаблон все равно воспринимался подобным образом.
В общем, это давно уже неактуально.

Добавлено через 10 минут
daslex, просто хочу добавить, что это неактуально как минимум с С++03 (редакция стандарта 2003 года).
3
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
10.10.2015, 21:36  [ТС] #19
После оговоренной темы, идет следующая. (5.3 Шаблоны членов классов). Вроде бы понятна, но есть кое что, чего я не осознаю. Пример комментировать не буду. Он не из книги, он - моя попытка реализации того, что пытаются донести в книге.

Я застрял на возвращаемом значении.
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
#include <iostream>
 
using namespace std;
 
template <typename T>
class MyClass{
    T value;
public:
    T get_value();
    void set_value(const T &x);
    MyClass(const T &x):value(x) {}
 
    template <typename T2>
    T& operator = (T2 &) ;
};
 
template <typename T>
 T MyClass<T>::get_value(){
    return (*this).value;
}
 
template <typename T>
void MyClass<T>::set_value(const T &x)  {
    value = x;
}
 
template <typename T>
   template <typename T2>
T& MyClass<T>::operator = (T2 &temp_class) {
    MyClass<T>::value = temp_class.get_value();  //Через геттер и сеттер у меня не получается
    return *this;   /* <----- Вот здесь застрял. */
}
 
 
int main(){
    MyClass<int>    Num1(20);
    MyClass<double> Num3(3.14);
   Num3 = Num1; 
}
Увы, но я, действительно не понимаю, чего от меня ждет компилятор.
0
nmcf
6243 / 5555 / 2526
Регистрация: 14.04.2014
Сообщений: 23,353
10.10.2015, 21:45 #20
А почему возвращается T, а не MyClass?
1
10.10.2015, 21:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.10.2015, 21:45
Привет! Вот еще темы с решениями:

Шаблоны, "invalid iterator range"
написать шаблонную функцию которая копирует значения с интервала...

Шаблоны. Класс "Очередь"
Как исправить ошибку? #include &lt;iostream&gt; using namespace std; ...

Создать класс "Книга" с полями "название книги", "количество страниц", "год издания"
Создать класс Книга поля: название книги,количество страниц,год издания...

«Шаблоны шаблонов» vs «шаблоны с параметрами-шаблонами».
«Шаблоны шаблонов» vs «шаблоны с параметрами-шаблонами». Есть ли разница в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

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