Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.78/40: Рейтинг темы: голосов - 40, средняя оценка - 4.78
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606

Шаблоны функции и указатель на функцию передаваемый в функцию

19.05.2017, 05:16. Показов 8125. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет! Вопрос такой: Если я пишу сортировку, например, bubbleSort и хочу помимо массива и его размера передать ещё и указатель на функцию, которая будет отвечать за последовательность сортировки по убыванию или по возрастанию... но сортировка должна специализировать типы данных во время выполнения. Вот как я хотел сделать:
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
template<typename T>
bool ascending(T a, T b)
{
    return a < b;
}
 
template<typename T>
bool descending(T a, T b)
{
    return a > b;
}
 
template<typename T>
void bubbleSort(T* a, const int size, bool(*compare)(T, T))
{
    for(int i = 0; i < size - 1; i++)
    {
        int index = i;
        for(int j = i + 1; j < size; j++)
        {
            if(compare(a[index], a[j])
            {
                index = j;
            }
        }
        T temp = a[i];
        a[i] = a[index];
        a[index] = temp;
    }
}
Конечно же, не получилось, указывает в ошибках на шаблоны во вспомогательных функциях, но как тогда быть с типами во вспомогательных функциях.
В чём моя ошибка, сам не могу разобраться, но ,уверен, что здесь помогут)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.05.2017, 05:16
Ответы с готовыми решениями:

Как сделать функцию, возвращающую указатель на функцию (которая в свою очередь возвращает указатель на массив)
Изучаю c++ по одной книжке.Она говорить не умеет.. Так вот понадобилось написать функцию,которая как параметр получает указатель на...

Параметр передаваемый в функцию
Добрый день, уважаемые, посетители форума. Вот я написал быструю сортировку: // quicksort.cpp: главный файл проекта. #include...

В функцию-метод передать указатель на другую функцию-метод и вызвать через переданный указатель
Друзья! Всем привет. Вот код: class otets { public: void f (void (otets::*p)()); private: void echo_f (){}; ...

38
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
21.05.2017, 21:18
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Liss29 Посмотреть сообщение
Интересный код, только столько операцй отрицания, что мозг отказывается понимать что к чему зачем параметры в ascending(b,a) поменяли местами? Что бы получить обратный результат?!
Этот код простая констатация того что если определена операция сравнения на меньше или больше, остальные в тривиальном случае следуют из неё и не нуждаются в самостоятельном определении. Вы же видите, что descending не использует своей логики. Он использует ascending. Общность состоит в том, что как бы ни была определена ascending код descending это обстоятельство не интересует. Он просто использует результат.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
21.05.2017, 21:34  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename elementType1, int numberOfElements1>
        Test<elementType, numberOfElements>& operator=(const Test<elementType1, numberOfElements1>& right)
        {
            if(numberOfElements != numberOfElements1)
            {
                            //size = right.size;
                            //delete[] array;
                array[numberOfElements1];
            }
            for(int i = 0; i < numberOfElements1; i++)
                array[i] = right.array[i];
            return *this;
        }
Это я пытаюсь изобразить операцию присваивания, но если размеры объектов различны, то ничего не получается. И ещё хочу узнать, если типы различны, то нужно как-то приобразовывать типы, но как это делать, если заранее не известно, что к чему приобразовывается. Это на себя берёт компилятор?
И ещё если шаблон объявлен как template<typename elementType, int numberOfElements> , то как определить шаблон для второго параметр(объекта), если функция расположена вне определения шаблона класса, если так template<typename elementType1, int numberOfElements1> ошибка. Правильно я понял, что такое можно проделать только в определении шаблона класса?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
21.05.2017, 21:43
Цитата Сообщение от Liss29 Посмотреть сообщение
Это я пытаюсь изобразить операцию присваивания
Шаблоны это наверное одна из сложнейших областей и я не смогу ответить на большую часть вопросов. Особенно когда ничего не видно. Вообще, обобщение присваивания это не мене весёлая штука чем обобщение сравнения. Хотелось бы увидеть код поподробнее и понять в чём цель. Ну то есть, если задача состоит в достижении возможности присвоения чего угодно чему угодно, то это может потребоваться где угодно и быть оправдано какой угодно целью.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
21.05.2017, 22:20  [ТС]
Цель сделать шаблон класса Array этот класс писал автор книги в целях демонстрации перегрузки операций, в данной главе он требует сделать шаблон этого класса с Одним типовым параметром и одним нетиповым параметром, вот код:
Работает всё, кроме присваивания, точнее, как я и писал выше, если присваивать объекты одного типа и одинакового размера, то всё проходит, а если хотя бы размер не одинаков, то ошибка.
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef TEST_H
#define TEST_H
 
#include <iostream>
using std::ostream;
using std::istream;
 
template<typename elementType, int numberOfElements>
class Test
{
    friend ostream& operator<<(ostream&, const Test<elementType, numberOfElements>&);
    friend istream& operator>>(istream&, Test<elementType, numberOfElements>&);
    public:
        Test();
        //Test(int);
        //Test(int, int); //конструктор получет два параметра первый размер массива, второй чем запонить массив
        Test(const Test&);
        ~Test();
 
        /*Test& operator=(const Test& right)
        {
            if(this != &right)
            {
                if(size != right.size)
                {
                    size = right.size;
                    array[size];
                }
                for(int i = 0; i < size; i++)
                    array[i] = right.array[i];
            }
            return *this;
        }*/
        
        template<typename elementType1, int numberOfElements1>
        Test<elementType, numberOfElements>& operator=(const Test<elementType1, numberOfElements1>& right)
        {
            if(numberOfElements != numberOfElements1)
            {
                Test<elementType1, numberOfElements1>();
            }
            for(int i = 0; i < numberOfElements1; i++)
                array[i] = right.array[i];
            return *this;
        }
        
 
        bool operator==(const Test&) const;
        bool operator!=(const Test& right) const
        {
            return !(*this == right);
        }
        
        elementType& operator[](int);
        elementType operator[](int) const;
 
        int getSize() const;
    private:
        int size;
        elementType* sPtr;
        elementType newArray;
        elementType array[numberOfElements];
};
 
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
 
#include <iomanip>
using std::setw;
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test():size(numberOfElements)
{
    for(int i = 0; i < size; i++)
        array[i] = 0;
 
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(int s):size((s > 0) ? s : 10)
{
    sPtr = new elementType[size];
    for(int i = 0; i < size; i++)
        sPtr[i] = 0;
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(int s, int simbol):size((s > 0) ? s : 10)
{
    sPtr = new elementType[size];
    for(int i = 0; i < size; i++)
        sPtr[i] = simbol;
}
 
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(const Test<elementType, numberOfElements>& arr):size(arr.numberOfElements)
{
    //sPtr = new typeElement[size];
    newArray[size];
 
    for(int i = 0; i < size; i++)
        newArray[i] = arr.array[i];
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::~Test()
{
    delete[] sPtr;
    //delete[] array;
}
 
 
template<typename elementType, int numberOfElements>
bool Test<elementType, numberOfElements>::operator==(const Test<elementType, numberOfElements>& right) const
{
    if(size != right.size)
        return false;
    for(int i = 0; i < size; i++)
        if(sPtr[i] != right.sPtr[i])
            return false;
    return true;
}
 
 
 
template<typename elementType, int numberOfElements>
elementType& Test<elementType, numberOfElements>::operator[](int index)
{
    if(index < 0 || index >= size)
    {
        cerr << "\nErroe subscript " << index << " out of range" << endl;
        system("Pause");
        exit(1); //завершить программу,т.к. индекс вне диапазона
    }
    
    return array[index];
}
 
template<typename elementType, int numberOfElements>
elementType Test<elementType, numberOfElements>::operator[](int index) const
{
    if(index < 0 || index >= size)
    {
        cerr << "\nErroe subscript " << index << " out of range" << endl;
        system("Pause");
        exit(1); //завершить программу,т.к. индекс вне диапазона
    }
    
    return array[index];
}
 
 
template<typename elementType, int numberOfElements>
int Test<elementType, numberOfElements>::getSize() const 
{
    return size;
}
 
template<typename elementType, int numberOfElements>
ostream& operator<<(ostream& os, const Test<elementType, numberOfElements>& right)
{
    int i;
    for(i = 0; i < right.size; i++)
    {
        if((i + 1) % 15 == 0)
            os << endl;
        os << setw(5) << right.array[i]; 
    }
    if(i % 15 == 0)
        os << endl;
 
    return os;
}
 
template<typename elementType, int numberOfElements>
istream& operator>>(istream& input, Test<elementType, numberOfElements>& right)
{
    input >> setw(right.size) >> right;
    return input;
}
#endif
Добавлено через 6 минут
Объект array должен выполнять если не все, то хотя бы часть функций, которые выполняют массивы в стиле C, но при это нужно контролировать выход за пределы массива, заполнение массива значениями, вывод массива(в табулированной форме), присваивание одного массива другому, присваивание литерала объекту, сравнение объектов(массивов) вот вкратце и всё, думаю, на начальном этапе хватит. тут цель не добавить функционал, а разобраться, как работать с шаблонами классов, я так думаю)
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
21.05.2017, 22:58
Цитата Сообщение от Liss29 Посмотреть сообщение
если присваивать объекты одного типа и одинакового размера, то всё проходит, а если хотя бы размер не одинаков, то ошибка.
Цитата Сообщение от Liss29 Посмотреть сообщение
Цель сделать шаблон класса Array
Где вы используете константу numberOfElements и зачем нужна size?
Цитата Сообщение от Liss29 Посмотреть сообщение
присваивать объекты одного типа
Для присваивания объектов разных типов вам придётся писать метод для разных типов. Это значит что в шаблоне ещё один тип-параметр должен быть. Тогда при совместимых типах можно заставить компилятор провести преобразование. Вот что я имею ввиду:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<typename A, typename B>
A& assign_whatsoever(A& a, B&b){
return a+=b;
}
int main(int argc, char* argv[])
{
float a=3;
int b=4;
a=assign_whatsoever(a,b);
cout<<a<<endl;//7 компилятор видит преобразование int -> float 
char* c="mama daragaya";
//а тут не получается
//a=assign_whatsoever(a,c);//: error C2440: +=: невозможно преобразовать 'char *' в 'float'
cout<<endl;
system("pause");
return 0;
}
хотя я бы сконцентрировался на понятии типа и поперегружал бы операции для одного типа и повыделял бы память для него же. Тогда идея присваивания массивов разной длины не покажется удачной и будет легче учить более сложные вещи.
Идея написать кучу специализаций для осуществления присваивания массивов разных типов тоже не вдохновляет. Может пусть ограничится своим типом?
При присваивании разно размерных однотипных даже:
Дело в том, что класс это только оболочка. Внутри у Вас массив. При несовместимости по размеру придётся удалить и создать новый. Так не проще ли сконструировать новый экземпляр класса?
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
21.05.2017, 23:48  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Где вы используете константу numberOfElements и зачем нужна size?
size - размер, в конструкторе инициализировал размер массива, прежде был указатель на конкретный тип данных, сейчас хотел size инициализировать значеним не типового параметра numberOfElements.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Это значит что в шаблоне ещё один тип-параметр должен быть
Автор в задании говорит, только, об одном типовом параметре и одном не типовом, вот текст задания:
Используя целый нетиповой параметр numberOfElements и типовой параметр elementType, создайте шаблон класса Array (рис. 11.6-11.7), который мы разра*ботали в главе 11. Этот шаблон позволит создавать экземпляры класса Array с заданным числом элементов указанного типа, определенным во время компиляции.

Всё остальное это мои предположения и желания чуть-чуть понять работу шаблонов классов и функций так как очень слабо владею этипм предметом.

По сути я задание зделал, создаю объект в майне, как он, автор книги, и требует, а какие-то действия с этими объектами не предусмотрены в задании.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Так не проще ли сконструировать новый экземпляр класса?
Что имеется ввиду? Класс для массива с новым размером? или я чего-то недопонял. Короче говоря, в данном случае, не стоит заморачиваться с выделением места для нового массива. С указателями проще, удалил delete[] ptr выделит new место под новый размер и радуйся, а тут значит так не пройдёт. Что ж это то, что я и хотел узнать.


Цитата Сообщение от IGPIGP Посмотреть сообщение
хотя я бы сконцентрировался на понятии типа и поперегружал бы операции для одного типа и повыделял бы память для него же.
Кликните здесь для просмотра всего текста
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
int main()
{
    Test<int, 10> test1;
    Test<double, 5> test2;
    Test<char, 5> test3(5);
    Test<int, 8> test4;
 
    cout << test4;
 
    test4 = test1;
 
    cout << test4;
 
    cout << test1.getSize() << endl;
 
    test1[0] = 11;
    test1[1] = 21;
    test1[8] = 71;
    int i = 0;
    while(1)
    {
        cin >> test2;
    }
    cout << test2;
 
    cout << test1;
 
    system("Pause");
    return 0;
 
}

поперегружал уже.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.05.2017, 00:52
Цитата Сообщение от Liss29 Посмотреть сообщение
сейчас хотел size инициализировать значеним не типового параметра numberOfElements.
Зачем? Константа - параметр шаблона уже задаёт размер. Иначе она же просто лишняя. И в этом смысле:
Цитата Сообщение от Liss29 Посмотреть сообщение
С указателями проще, удалил delete[] ptr выделит new место под новый размер
совсем непонятно. То есть, нужно сначала выбрать стратегию. Если автор книги которому Вы следуете предлагает :
Цитата Сообщение от Liss29 Посмотреть сообщение
Используя целый нетиповой параметр numberOfElements и типовой параметр elementType, создайте шаблон класса Array
то ни о каком изменении размера речи не пойдёт. То есть присвоение возможно лишь когда размеры совпадут. Благо, типы с разными константами-параметрами шаблона это разные типы и сама конструкция не даст Вам даже попытаться присвоить массивы разных размеров. А вот применение size в данном контексте, это уже попытка создать свой маленький уютный компилятор в инстансе шаблонного класса. Поэтому я и предложил оставить пока шаблоны.

Добавлено через 44 минуты
Вот перед сном всё о том же:
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
#include <iostream>
using namespace std;
 
template< typename T>
void show_container(T it_start, T it_end ){
while(it_start != it_end) cout << *it_start++ ;
cout<<endl;
}
 
 
const size_t n=10;
int a[n];
template <size_t N, typename T, T(&array_T)[N]>
struct Array_T{
    Array_T(){for(size_t i=0; i<N; ++i)array_T[i]=0;}
     T* get_iter(size_t i){ return &array_T[i];  }
 
};
 
//но вышепоказанный тип нуждается в глобальном массиве в качестве параметра
//ещё хуже то что любой инстанс укажет на этот же массив (см. код)
//или
template<typename T, size_t length>
struct Arra{
//константа length позволяет создавать массив не выделяя память вручную:
T arra[length];//а тут это всегда свой массив
Arra(){
for(size_t i=0; i<length; ++i)arra[i]=0;
}
size_t get_length(){return length;}
 
Arra& operator == (const Arra& rhs){
    if(this!=&rhs && length == rhs.get_length()){
for(size_t i=0; i<length; ++i)arra[i]=rhs.arra[i];
    }
    return *this;
}
};
 
int main(int argc, char* argv[])
{
Array_T<n, int, a> arr_T1;
show_container(arr_T1.get_iter(0), arr_T1.get_iter(n));
Array_T<n, int, a> arr_T2;
*arr_T2.get_iter(0)=123;
cout<<*arr_T1.get_iter(0)<<endl;
 
Arra<int, 5> arra1;
show_container(&(arra1.arra[0]) , &(arra1.arra[0])+arra1.get_length());
Arra<int, 5> arra2;
arra2.arra[1]=123;
show_container(&(arra2.arra[0]) , &(arra2.arra[0])+arra2.get_length());
show_container(&(arra1.arra[0]) , &(arra1.arra[0])+arra1.get_length());
 
arra1=arra2;
show_container(&(arra1.arra[0]) , &(arra1.arra[0])+arra1.get_length());
cout<<endl;
system("pause");
return 0;
}
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
22.05.2017, 04:56  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Константа - параметр шаблона уже задаёт размер.
Это понятно int Test<elementType, numberOfElements>::getSize() const{return numberOfElements;} первоначально было так.


В классах везде значит надо писать
C++
1
2
template<typename T, int length>
имя class<T, length>&  область действия_class<T, length>::имя_функции(const имя типа<T, length>&)
А у тебя как-то более компактно код написан, хотя и несовсем мне понятны некоторые фрагменты кода, в стуктурах есть отличия в написании кода для шаблонов?

Правильно понимаю, что в коде, для задания, явная реализаця операции присваивания не нужна?

Что значит: переопределить шаблон явным определением класса Array для типа float? Заново что ли писать класс только с заголовком
C++
1
template<typename elementType = float> class Test{};
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.05.2017, 09:22
Цитата Сообщение от Liss29 Посмотреть сообщение
в стуктурах есть отличия в написании кода для шаблонов
кроме квалификаторов доступа по умолчанию (которые в данном демо значения не имеют) нет разницы. И вот опять Liss29, вопросы которые говорят, что есть же что учить до шаблонов.
Цитата Сообщение от Liss29 Посмотреть сообщение
Правильно понимаю, что в коде, для задания, явная реализаця операции присваивания не нужна?
Почему нет? Просто нужно определиться когда она нужн имеет смысл, а когда нет. В случае когда массивы одного типа и длины тогда она вполне заслуживает реализации. Напишите класс - массив типа int и посмотрите всё. Напишите с ручным выделением памяти. Потом стек и очередь для комплекта. Легче с шаблонами будет тогда, когда с нешаблонами реально легко.
Цитата Сообщение от Liss29 Посмотреть сообщение
Что значит: переопределить шаблон явным определением класса Array для типа float?
Возможно имеется в виду специализация. Вы определяете (перегружаете) шаблон конкретными параметрами. Это имеет смысл если вы изменяете функционал.
В таком роде:
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
template<size_t length>
struct Arra<float, length>{
//константа length позволяет создавать массив не выделяя память вручную:
float arra[length];//а тут это всегда свой массив
Arra(){
for(size_t i=0; i<length; ++i)arra[i]=0;
}
 
// расширение функциональности (хотя это, как раз, можно бы обобщить и для типа-параметра Т)
Arra( float *fl ){
for(size_t i=0; i<length; ++i)arra[i]=fl[i];
}
 
size_t get_length(){return length;}
 
Arra& operator == (const Arra& rhs){
    if(this!=&rhs && length == rhs.get_length()){
for(size_t i=0; i<length; ++i)arra[i]=rhs.arra[i];
    }
    return *this;
}
//эта функция чревата переполнением по результату и нужна лишь для
//демонстрации расширения функциональности
int get_all_integer_part(){
int sum(0);
for(size_t i=0; i<length; ++i)sum+=static_cast<int>(arra[i]);
return sum;
}
};
 
int main(int argc, char* argv[])
{
float af[]={1.1f, 2.2f, 3.3f, 4.4f, 5.5f};
Arra<float,5> af_af(af);
cout<<af_af.get_all_integer_part()<<endl;
system("pause");
return 0;
}
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
22.05.2017, 21:17  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
И вот опять Liss29, вопросы которые говорят, что есть же что учить до шаблонов
Ты что, думаешь, я специально начал изучение с шаблонов, нет, но структуры в книге Дейтелов как-то не проходят особо, всё что я о них, о структурах знаю, это то, что сам почерпнул то тут, то там в различных источниках. Лучше спросить, если не знаешь чего-то конкретно, чем молчать и строить из себя умника, когда суть вопроса до конца не ясна, не так ли?

Цитата Сообщение от IGPIGP Посмотреть сообщение
Легче с шаблонами будет тогда, когда с нешаблонами реально легко.
Уже написано, но с шаблонами легче не стало, сейчас дополнительно почитаю статьи в интернете, может что и пойму.

Возможно имеется в виду специализация.
Вот видишь, даже ты сомневаешься, что это и зачем, а я тем более. Если с шаблоном функции, то понятно, пишется шаблонная/не шаблонная функция с тем же именем, но разными параметрами и реализацией. А тут возник вопрос, где его писать, отдельно от уже созданного класса Array(у меня Test) или внутри как-то приспасабливать, если отдельно, то как это выглядит при подключении в файле main() там у меня уже подключен Test.h вопрос в этом в основном.

А так я тоже накалякал кое что)
Кликните здесь для просмотра всего текста
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
template<int numberOfElements>
#ifndef TEST_H
#define TEST_H 
 
class Test<float, numberOfElements>
{
    public:
        Test();
        int getSize() const
        {
            return numberOfElements;
        }
        
        bool operator==(const Test&) const;
        bool operator!=(const Test& right) const
        {
            return !(*this == right);
        }
    private:
        elementType array[numberOfElements];
};
 
#include <iostream>
using std::cout;
using std::endl;
 
template<typename elementType = float, int numberOfElements>
Test<elementType, numberOfElements>::Test()
{
    cout << "clss Test is Test<float>" << endl;
    for(int i = 0; i < numberOfElements; i++)
        array[i] = 0;
}
 
template<typename elementType = float, int numberOfElements>
bool Test<elementType, numberOfElements>::operator==(const Test<elementType, numberOfElements>& right) const
{
    if(numberOfElements != right.numberOfElements)
        return false;
    for(int i = 0; i < numberOfElements; i++)
        if(array[i] != right.array[i])
            return false;
    return true;
}
#endif

Но меня терзают смутные сомнения, если честно.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Это имеет смысл если вы изменяете функционал
Да нет, там всё гораздо прозаичнее:
Кликните здесь для просмотра всего текста
Напишите программу, в которой используется шаблон класса Array. Из этого шаблона может быть получен представитель класса Array для любого типа элементов. Переопределите шаблон явным определением класса Array для типа float (class Array< float >). В программе-драйвере создайте представитель класса Array типа int при помощи шаблона и покажите, что при создании представителя класса Array типа float используется явное определение класса class Array< float >.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.05.2017, 21:55
Цитата Сообщение от Liss29 Посмотреть сообщение
Да нет, там всё гораздо прозаичнее:
судя по тексту это именно явная специализация и есть. Она почему-то у автора названа явным определением. Может перевод плохой. Или автор. Но как я понял имеется в виду именно явная и именно частичная специализация.
Цитата Сообщение от Liss29 Посмотреть сообщение
Вот видишь, даже ты сомневаешься, что это и зачем
Это моё кредо даже там, где я чувствую себя достаточно основательно. А в плюсах и подавно.
В данном случае, неуверенность связана с тем, что я не вижу всей задачи (её текста) и поэтому вынужден немного гадать.
Однако, возвращаясь к теме, - явная специализация, это перегрузка шаблона для конкретного случая. Она имеет смысл если логика для указанного случая отличается от общего алгоритма. Пример я показал. Как смог.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
23.05.2017, 06:15  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Пример я показал. Как смог.
Не знаю у меня ничего не получается так ведь должно выглядет явная частичная специализация шаблона класса:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
template<int numberOfElements> class Test<float, numberOfElements>
{
    public:
        Test();
 
        int getSize() const { return numberOfElements; }
    private:
        float array[numberOfElements];
};
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.05.2017, 08:08
Цитата Сообщение от Liss29 Посмотреть сообщение
Не знаю у меня ничего не получается так ведь должно выглядет явная частичная специализация шаблона класса:
мой пример работает. Сравните свой код и мой. Только полностью, - начиная от описания шаблона. Или положите весь код + сообщение компилятора о ошибке.
Вопрос вроде:
Цитата Сообщение от Liss29 Посмотреть сообщение
у меня ничего не получается
ничего не говорит о предмете.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
23.05.2017, 20:36  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
мой пример работает.
Мой тоже работает дело оказалось вот в чём, у меня студия старая, как ...авно мамонта, я решил попробовать откомпилировать на 2008 и 2010 на них код нормально компилируется-линкуется и работает как надо, как требует автор в задании.
Вот код:
Кликните здесь для просмотра всего текста
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#ifndef TEST_H
#define TEST_H
 
#include <iostream>
using std::ostream;
using std::istream;
 
 
template<typename elementType, int numberOfElements>
class Test
{
    friend ostream& operator<<(ostream&, const Test<elementType, numberOfElements>&);
    friend istream& operator>>(istream&, Test<elementType, numberOfElements>&);
    public:
        Test();
        Test(int);
        Test(int, int); //конструктор получет два параметра первый размер массива, второй чем запонить массив
        Test(const Test&);
        ~Test();
        
        template<typename elementType1, int numberOfElements1>
        Test<elementType, numberOfElements>& operator=(const Test<elementType1, numberOfElements1>& right)
        {
            if(numberOfElements != numberOfElements1)
            {
                Test<elementType1, numberOfElements1>();
            }
            for(int i = 0; i < numberOfElements1; i++)
                array[i] = right.array[i];
            return *this;
        }
        
        
        bool operator==(const Test&) const;
        bool operator!=(const Test& right) const
        {
            return !(*this == right);
        }
        
        elementType& operator[](int);
        elementType operator[](int) const;
 
        int getSize() const;
    private:
        int size;
        elementType* sPtr;
        elementType array[numberOfElements];
};
 
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
 
#include <iomanip>
using std::setw;
 
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test():size(numberOfElements)
{
    for(int i = 0; i < size; i++)
        array[i] = 0;
 
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(int s):size((s > 0) ? s : 10)
{
    sPtr = new elementType[size];
    for(int i = 0; i < size; i++)
        sPtr[i] = 0;
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(int s, int simbol):size((s > 0) ? s : 10)
{
    sPtr = new elementType[size];
    for(int i = 0; i < size; i++)
        sPtr[i] = simbol;
}
 
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::Test(const Test<elementType, numberOfElements>& arr):size(arr.numberOfElements)
{
    //sPtr = new typeElement[size];
    newArray[size];
 
    for(int i = 0; i < size; i++)
        newArray[i] = arr.array[i];
}
 
template<typename elementType, int numberOfElements>
Test<elementType, numberOfElements>::~Test()
{
    delete[] sPtr;
    //delete[] array;
}
 
 
template<typename elementType, int numberOfElements>
bool Test<elementType, numberOfElements>::operator==(const Test<elementType, numberOfElements>& right) const
{
    if(size != right.size)
        return false;
    for(int i = 0; i < size; i++)
        if(sPtr[i] != right.sPtr[i])
            return false;
    return true;
}
 
 
 
template<typename elementType, int numberOfElements>
elementType& Test<elementType, numberOfElements>::operator[](int index)
{
    if(index < 0 || index >= size)
    {
        cerr << "\nErroe subscript " << index << " out of range" << endl;
        system("Pause");
        exit(1); //завершить программу,т.к. индекс вне диапазона
    }
    
    return array[index];
}
 
template<typename elementType, int numberOfElements>
elementType Test<elementType, numberOfElements>::operator[](int index) const
{
    if(index < 0 || index >= size)
    {
        cerr << "\nErroe subscript " << index << " out of range" << endl;
        system("Pause");
        exit(1); //завершить программу,т.к. индекс вне диапазона
    }
    
    return array[index];
}
 
 
template<typename elementType, int numberOfElements>
int Test<elementType, numberOfElements>::getSize() const 
{
    return size;
}
 
template<typename elementType, int numberOfElements>
ostream& operator<<(ostream& os, const Test<elementType, numberOfElements>& right)
{
    int i;
    for(i = 0; i < right.size; i++)
    {
        if((i + 1) % 15 == 0)
            os << endl;
        os << setw(5) << right.array[i]; 
    }
    if(i % 15 == 0)
        os << endl;
 
    return os;
}
 
template<typename elementType, int numberOfElements>
istream& operator>>(istream& input, Test<elementType, numberOfElements>& right)
{
    input >> setw(right.size) >> right;
    return input;
}
 
//======явная частичная спецификация шаблона класса ================
template<int numberOfElements> class Test<float, numberOfElements>
{
    public:
        Test()
        {
            cout << "Constructor from Test is float" << '\n';
            for(int i = 0; i < numberOfElements; i++)
                array[i] = 0;
        }
        
        bool operator==(const Test& right) const 
        {
            if(numberOfElements != right.numberOfElements)
                return false;
            for(int i = 0; i < numberOfElements; i++)
                if(array[i] != right.array[i])
                    return false;
            return true;
        }
 
        bool operator!=(const Test& right) const
        {
            return !(this == right);
        }
        
        Test<float, numberOfElements>& operator[](int index)
        {
            if(index < || index >= numberOfElements)
            {
                cout << "Error:" << endl;
                exit(1);
            }
            return array[index];
        }
        int getSize() const { return numberOfElements; }
    private:
        float array[numberOfElements];
};
 
#endif

Но ещё много вопросов осталось по этой теме.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.05.2017, 20:45
Цитата Сообщение от Liss29 Посмотреть сообщение
Но ещё много вопросов осталось по этой теме.
Liss29, уберите size и пользуйтесь numberOfElements. Указатель как член вам тоже не нужен - уберите и elementType* sPtr;
Избавьтесь от выделения и освобождения явно. Если у Вас есть массив elementType array[numberOfElements]; то не нужно ничего. Только имя пересекается с std::array но это не страшно. Это гадко, но пока не зацепит не поймёте. У меня например arra и др. Я не горжусь данными изысками, но думаете это от пресыщенности бытиём я сочиняю? Остальное не смотрел. Чтобы не огорчать. Но в целом, если Вам нравится, то это уже результат.

добавлю уже при редактировании данного повтора. 15 секунд это не спроста. Это !%. Думаю внечеловеческий разум пытается нам рассказать, что !% это повторение. Хотя не уверен.
Добавлено через 15 секунд
Цитата Сообщение от Liss29 Посмотреть сообщение
Но ещё много вопросов осталось по этой теме.
Liss29, уберите size и пользуйтесь numberOfElements. Указатель как член вам тоже не нужен - уберите и elementType* sPtr;
Избавьтесь от выделения и освобождения явно. Если у Вас есть массив elementType array[numberOfElements]; то не нужно ничего. Только имя пересекается с std::array но это не страшно. Это гадко, но пока не зацепит не поймёте. У меня например arra и др. Я не горжусь данными изысками, но думаете это от пресыщенности бытиём я сочиняю? Остальное не смотрел. Чтобы не огорчать. Но в целом, если Вам нравится, то это уже результат.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
23.05.2017, 21:21  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но в целом, если Вам нравится, то это уже результат.
Как сказать, нравится не нравится, нервов затрачено немерено, чтобы получить хоть такой результат. По поводу того, что убрать указатель и size я это понял.

Если бы я захотел создавать объекты массива Test<тип> test, а не Test<тип, количество>, то для этого нужно создавать ещё один класс, допустим так: template<typename T> class Test{//....}; так?
явно специализировать не поучиться ведь?
По сути это идентичный по функционалу класс получится, а значит займёт лишнюю память это же не айс.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.05.2017, 21:49
Цитата Сообщение от Liss29 Посмотреть сообщение
Если бы я захотел создавать объекты массива Test<тип> test
Вот тут и проявляется знание основ. Liss29, если Вы хотите пользоваться преимуществом массива-члена, то в C++ нужно показать компилятору константу времени компиляции (то есть constexpr). В противном случае не имеет смысла делать константу параметром шаблона. Тогда вы можете иметь параметр - тип, а размер получать в конструкторе. Тогда придётся выделять или удалять вручную или использовать std::vector или list... Но тогда придётся следит за равенством длин самостоятельно. Это нужно например вот почему. Раз уж перегрузка присваивания это свежая для Вас тема, представьте, что вы создали три объекта класса-массива целых чисел : a[3], b[3], c[10] (это псевдо описание)
Далее массив объекта a Вы заселили последовательностью 1, 2, 3
b и с содержат мусор.
Поскольку Ваш класс не зависит от размера то a,b,c это один и тот же тип то Вы можете присвоить любой любому в любой последовательности. Теперь если b=a всё нормально, - в b содержатся 1, 2, 3. А вот если с=a то семь элементов не содержат ничего хорошего. Как быть? Контролировать размер достоверных данных? Это путь на Голгофу. Менять размер перевыделением? Лучше уже путь на Голгофу. Дело в том, что создать новый объект может оказаться проще, чем перевыделять старый.
Хотя если интересно - сделайте. Но лучше бы всё это поделать без шаблонов.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,606
23.05.2017, 23:29  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
В противном случае не имеет смысла делать константу параметром шаблона.
Ну-с тут, как говорится, только ради обучения и демонстрации сделано включение этого не типового параметра шаблона (константы). Хотя и говорится в тексте главы, что желательно объявлять размер контейнеров именно так, через параметры шаблона. На данный момент у меня ещё не сложилась ясной картины что нужно, а что нет и для чего нужно, а для чего нет.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Менять размер перевыделением?
Тут меня прям коробит, чтобы не сказать иначе, а как до этого размер массива меняли, когда работал без шаблонов и массив задавался через указатели, тогда особых сложностей не составляло, если нужно, уменьшить или увеличить размер массива. А теперь значит, так уже не прокатывает, что за тема такая мистическая эти шаблоны.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.05.2017, 08:54
Цитата Сообщение от Liss29 Посмотреть сообщение
. Хотя и говорится в тексте главы, что желательно объявлять размер контейнеров именно так, через параметры шаблона. На данный момент у меня ещё не сложилась ясной картины что нужно, а что нет и для чего нужно, а для чего нет.
Цитата Сообщение от Liss29 Посмотреть сообщение
Тут меня прям коробит, чтобы не сказать иначе, а как до этого размер массива меняли, когда работал без шаблонов и массив задавался через указатели, тогда особых сложностей не составляло,
Liss29, я не говорю, что это плохо. Такой контейнер как std::vector так и делает. Но в самом начале я сказал о том, что нужно вначале определиться со стратегией, а потом уже ей неуклонно следовать. Нельзя бежать в противоположных направлениях сохраняя консистентность организма.
Ещё раз. Если вы объявляете константу определяющую размер параметром шаблона, это автоматически ведёт к созданию встроенного локального массива. Если не ломать свою же логику.
Иначе такой параметр не нужен. И вреден. Вы же пишете библиотеку не для того чтобы получать судебные иски от юзеров с обвинениями в крайних формах мизантропии?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.05.2017, 08:54
Помогаю со студенческими работами здесь

Ограничен ли буфер, передаваемый в функцию send
Вопрос: ограничен ли размер буфера, передаваемого в функцию send, размером MTU?

Работа с файлом (передать указатель на файл в функцию, вернуть указатель на файл из функции)
Подскажите как передать указатель на файл в функцию, как вернуть указатель на файл из функции. void Open() // из этой функции вернуть...

Можно ли в C++ определить функцию, которая возвращает указатель на функцию с той же сигнатурой?
Вопрос такой, а можно ли в C++ определить функцию, которая возвращает указатель на эту же функцию, то есть на функцию с такой же самой...

Как передавать указатель на функцию в функцию для ее выполнения?
Здравствуйте! Вопрос следующий: Как передавать указатель на функцию в функцию для ее выполнения? Например: &lt;хедер&gt; ... ...

Указатель на функцию в качестве параметра функции
ln(1-x)+sinx необходимо создать программу демонстрирующую возможность использования указателя на некоторую функцию в качестве параметра...


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

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru