Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
#1

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

19.05.2017, 05:16. Просмотров 658. Ответов 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;
    }
}
Конечно же, не получилось, указывает в ошибках на шаблоны во вспомогательных функциях, но как тогда быть с типами во вспомогательных функциях.
В чём моя ошибка, сам не могу разобраться, но ,уверен, что здесь помогут)
http://www.cyberforum.ru/cpp-beginners/thread1411830.html
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.05.2017, 05:16
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Шаблоны функции и указатель на функцию передаваемый в функцию (C++):

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

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

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

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

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

38
Antikl
с++
272 / 268 / 146
Регистрация: 15.07.2015
Сообщений: 1,475
Завершенные тесты: 6
19.05.2017, 05:39 #2
C++
1
2
3
4
5
6
7
8
 
template<class T>
void BubbleSort(T* arr, int size) {
  for (int i = 1; i < size; ++i)
    for (int j = size-1; j >= i; --j)
      if (arr[j-1] > arr[j])
        std::swap(arr[j], arr[j-1]);
}
0
GbaLog-
Любитель чаепитий
3156 / 1462 / 462
Регистрация: 24.08.2014
Сообщений: 5,179
Записей в блоге: 1
Завершенные тесты: 2
19.05.2017, 05:49 #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
#include <iostream>
 
template<typename T, typename Func>
void bubbleSort(T * arr, size_t size, Func && compare)
{
    for(int i = 0; i < size - 1; i++)
    {
        int index = i;
        for(int j = i + 1; j < size; j++)
        {
            if(compare(arr[index], arr[j]))
            {
                index = j;
            }
        }
        T temp = arr[i];
        arr[i] = arr[index];
        arr[index] = temp;
    }
}
 
int main()
{
    constexpr size_t size = 3;
    int arr[size]{ 3, 2, 1 };
    
    bubbleSort(arr, size, std::greater<int>());
    
    for (const auto & it : arr)
        std::cout << it << ' ';
}
1
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
19.05.2017, 20:45  [ТС] #4
GbaLog-
Я до таких изысков ещё не дошёл! как-то не совсем то, чего я хотел. Значит, если я определяю шаблон функции сортировки, то вспомогательные функции отсекаются т.к. они не знают, с какими типами данных я работаю, так?
0
GbaLog-
Любитель чаепитий
3156 / 1462 / 462
Регистрация: 24.08.2014
Сообщений: 5,179
Записей в блоге: 1
Завершенные тесты: 2
19.05.2017, 21:04 #5
не понимаю, что у тебя там не работает, у меня так всё работает:
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
#include <iostream>
 
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;
    }
}
 
int main()
{
    constexpr size_t size = 3;
    int arr[size]{ 3, 2, 1 };
    
    bubbleSort(arr, size, descending);
    
    for (const auto & it : arr)
        std::cout << it << ' ';
}
если у тебя ошибки, то показывай их.
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
20.05.2017, 05:25  [ТС] #6
Цитата Сообщение от GbaLog- Посмотреть сообщение
если у тебя ошибки, то показывай их.
D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(43) : error C2958: the left parenthesis '(' found at 'D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(40)' was not matched correctly
D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(62) : error C2896: 'void __cdecl bubbleSort(T *,const int,bool (__cdecl *)(T,T))' : cannot use function template 'bool __cdecl ascending(T,T)' as a function argument
D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(21) : see declaration of 'ascending'
D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(63) : error C2896: 'void __cdecl bubbleSort(T *,const int,bool (__cdecl *)(T,T))' : cannot use function template 'bool __cdecl descending(T,T)' as a function argument
D:\Мои документы\Project\BubbleSort\BubbleSort.cpp(27) : see declaration of 'descending'
Вот ошибки! правда я не использую этих прибамбасов constexpr? просто объявляю, как const int.
вот моя main()
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const size_t size = 5;
    int intArray[size] = {2, 5, 3, 4, 1};
    double doubleArray[size] = {2.2, 5.5, 3.3, 4.4, 1.1};
    
    print(intArray, size);
    cout << endl;
    print(doubleArray, size);
    
        bubbleSort(intArray, size, ascending);
        bubbleSort(doubleArray, size, descending);
 
        print(intArray, size);
        cout << endl;
        print(doubleArray, size);
0
GbaLog-
Любитель чаепитий
3156 / 1462 / 462
Регистрация: 24.08.2014
Сообщений: 5,179
Записей в блоге: 1
Завершенные тесты: 2
20.05.2017, 09:23 #7
Цитата Сообщение от Liss29 Посмотреть сообщение
Вот ошибки!
хм, шаблонную функцию нельзя передавать в качестве указателя на функцию, переделай на функторы.
но вот почему нельзя - я не знаю, а предположения на этот счет не буду говорить, ибо они, скорее всего, окажутся не верными.
переделай на функторы
в твоем случае легче использовать std::greater и std::less.
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
20.05.2017, 21:03  [ТС] #8
Цитата Сообщение от GbaLog- Посмотреть сообщение
шаблонную функцию нельзя передавать в качестве указателя на функцию,
Вот это я и хотел узнать. С функторами у меня ничего не получается, не знаком я с ними.
0
GbaLog-
Любитель чаепитий
3156 / 1462 / 462
Регистрация: 24.08.2014
Сообщений: 5,179
Записей в блоге: 1
Завершенные тесты: 2
20.05.2017, 21:35 #9
http://www.cyberforum.ru/cpp/thread1087631.html
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
20.05.2017, 23:03  [ТС] #10
За материал, спасибо, прочту, ответ я уже получил, если, конечно, реализовать никак нельзя именно тот код, который я предоставил в самом начале, без этих самых функторов.

Если надо создать некий шаблон класса с типовыи и не типовым параметром, то как реализовывать перегрузку операций, так же как это делается в не шаблонных классах, только с добавлением везде
C++
1
template<typename T, int element>
, так? У меня ничего не получается почему-то вроде везде добавляю это определение. Реализация шаблона класса должна находиться в хедере, правильно? тут тоже мне не совсем всё понятно..
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
#ifndef TEST_H
#define TEST_H
 
#include <iostream>
using std::ostream;
using std::istream;
 
tempalte<typename T, int element>
class Test
{
    friend ostream& operator<<(ostream&, const Test<T,element>&);
friend istream& operator>>(istream&, Test<T, element>&);
public:
Test();
//задесь прототипы
priavte:
      int size;
      T array[element];
};
 
//здесь реализация идёт, так? а #endif на своё месте? 
tempalte<typename T, int element>
Test<T, element>::Test():size((element < 0) ? 10 : element))
{
 
}
 
//......
//в данном случае я всё правильно делаю или что-то упустил?
ostream& Test<T, element>::operator<<(ostream& os, const Test<T, element>& right)
{
       for(int i  = 0; i < right.size; i++)
             os << right.array[i] << ' ';
      return os;
}
#endif
Не могу толком в тему врубиться.

Добавлено через 48 минут
Цитата Сообщение от GbaLog- Посмотреть сообщение
Функторы, предикаты, функциональные адаптеры, лямбда-функции
Из всего текста понадобилась одна строка о том, какой нажо подключить хедер) Да сортирует, но повторюсь это не совсем то, чего я хотел от своей сортировки.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7002 / 3295 / 448
Регистрация: 04.12.2011
Сообщений: 9,119
Записей в блоге: 5
20.05.2017, 23:19 #11
Цитата Сообщение от Liss29 Посмотреть сообщение
Вот это я и хотел узнать.
Шаблонная функция инстанциируется на стадии компиляции. То есть, адреса как такового у инстанса ещё может не быть когда в коде его пытаются взять. Если написать обычную функцию в которой инстанциируется шаблонная, то адрес такой функции вполне можно передать.
Например:
C++
1
2
3
bool pred_char(char lhs, char rhs){
return templ_pred<char>(lhs,rhs);
}
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
20.05.2017, 23:49  [ТС] #12
Цитата Сообщение от IGPIGP Посмотреть сообщение
Если написать обычную функцию в которой инстанциируется шаблонная, то адрес такой функции вполне можно передать.
Сейчас узнаю, что такое инстанциируется и тогда, возможно, что-то пойму.
А если серьёзно, то я хотел всего лишь функцию сортировки сделать более универсальной, когда параметры типов передаваемых функции были известны, то всё работало замечательно, вот я и решил, прочитав про шаблоны сделать её, функцию, более-менее гибкой. Я понмаю, что способов решения этой и подобных задачь масса, но я опираюсь на знания, которыми я обладаю на данный момент только и всего.
1
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
20.05.2017, 23:59 #13
Цитата Сообщение от IGPIGP Посмотреть сообщение
Если написать обычную функцию в которой инстанциируется шаблонная, то адрес такой функции вполне можно передать.
Liss29, можно и не писать прослоек. Пример из шапки без изменений + main:
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
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;
    }
}
 
int main()
{
    const size_t size = 3;
    int arr[size] = { 3, 2, 1 };
    
    bubbleSort(arr, size, &descending<int>); // здесь
    
    for (size_t i = 0; i < size; ++i)
        std::cout << arr[i] << ' ';
}
Демо в онлайн компиляторе: http://rextester.com/FTD78103
4
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7002 / 3295 / 448
Регистрация: 04.12.2011
Сообщений: 9,119
Записей в блоге: 5
21.05.2017, 00:04 #14
Цитата Сообщение от Liss29 Посмотреть сообщение
Сейчас узнаю, что такое инстанциируется и тогда, возможно, что-то пойму.
А если серьёзно, то я хотел всего лишь функцию сортировки сделать более универсальной, когда параметры типов передаваемых функции были известны, то всё работало замечательно, вот я и решил, прочитав про шаблоны сделать её, функцию, более-менее гибкой. Я понмаю, что способов решения этой и подобных задачь масса, но я опираюсь на знания, которыми я обладаю на данный момент только и всего.
Щаблон это не простой код. Это описатель для генерации кода. То есть компилятор глядя на шаблон и на вызов генерирует то, что мы пишем когда определяем функцию явно. В том, что я написал нет ни слова правды, но так проще представить для начала.
А вообще:
Желание создать обобщения для сравнения штука спорная. В принципе сам предикат является частью описания конкретного типа и его обобщение это обобщение на уровне какого-то типа, всё равно. Если совсем уж философски, то выбор из таких параметров как
имя, фамилия, рост, вес, цвет, глубина, температура
первых четырёх формирует объект именно потому, что ученик / ученица класса сравнимы и отличимы именно этими параметрами. А температура (обычно) не является предикатом с высокой селективность по отношению к группе людей. Если они живые и не больные.
То есть, предикат это глубоко внутренняя логика типа и обобщать можно только на уровне типа (в иерархии в том числе). imho
1
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
21.05.2017, 03:45  [ТС] #15
DrOffset
Это уже ближе к истине. Но я сделал по совету выше с
C++
1
std::less<>() std::greate<>()
короче говоря не суть важно, вот ещё бы из
C++
1
&descending<int>
убрать этот <int> во тогда будет то, что я хотел. Но это уже не совсем то, так как это сделал не я.

Добавлено через 19 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Щаблон это не простой код.
Это я понимаю.
Цитата Сообщение от IGPIGP Посмотреть сообщение
Желание создать обобщения для сравнения штука спорная.
Это имеется ввиду для ascending и discending, но тогда так же ошибки формируются.
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.05.2017, 04:51 #16
Цитата Сообщение от Liss29
убрать этот <int> во тогда будет то, что я хотел.
Понятно что ты хочешь, но шаблонная функция не имеет адреса. Шаблон - это чертеж, на основе чертежа можно построить экземпляры. В частности, шаблон функции при подстановке аргумента "рождает" функцию, у которой уже можно взять адрес. Что и было продемонстрировано выше. У шаблона не может быть адреса, так же как не может быть адреса у чертежа здания, зато адрес может быть у готового строения. Улавливаешь аналогию?

Что тут можно сделать, чтобы обеспечить требуемую семантику? Можно создать функциональный объект (функтор), у которого есть шаблонная функция и передать этот объект. Смысл полученного кода останется прежним, изменится только запись и некоторые сущности поменяют свою природу - вместо указателя на функцию аргументом примем функциональный объект. Но нам ведь ехать надо, а не "шашечки", правда?
Кликните здесь для просмотра всего текста
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
#include <iostream>
 
struct Ascending
{
    template <typename T>
    bool operator()(T a, T b)
    {
        return a < b;
    }
};
 
struct Descending
{
    template<typename T>
    bool operator()(T a, T b)
    {
        return a > b;
    }
};
    
template <typename T, typename F>
void bubbleSort(T* a, const int size, F compare)
{
    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;
    }
}
 
int main()
{
    const size_t size = 3;
    int arr[size] = { 3, 2, 1 };
    
    bubbleSort(arr, size, Descending()); // здесь
    
    for (size_t i = 0; i < size; ++i)
        std::cout << arr[i] << ' ';
}

Если этот код тебе непонятен, то могут только посоветовать подучить непонятные аспекты. Потому что как-либо подругому сохранить нужное поведение будет нельзя.

Цитата Сообщение от Liss29
я сделал по совету выше
Тут главное не как ты сделал, а как ты понял, что ты сделал, и почему
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
21.05.2017, 06:59  [ТС] #17
Цитата Сообщение от DrOffset Посмотреть сообщение
Улавливаешь аналогию?
Улавливаю.

Цитата Сообщение от DrOffset Посмотреть сообщение
Тут главное не как ты сделал, а как ты понял, что ты сделал, и почему
Я понял, что я вообще ничего не понял из того, что прочёл в книге, вот это я отчётливо понял.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7002 / 3295 / 448
Регистрация: 04.12.2011
Сообщений: 9,119
Записей в блоге: 5
21.05.2017, 08:53 #18
Лучший ответ Сообщение было отмечено Liss29 как решение

Решение

Цитата Сообщение от Liss29 Посмотреть сообщение
Это имеется ввиду для ascending и discending, но тогда так же ошибки формируются.
этого не понял. Вот тут:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Желание создать обобщения для сравнения штука спорная.
я имел ввиду тот факт, что сам алгоритм сравнения швабр и оперных вокалов очень отличаются. В ваших шаблонах нет перегрузок алгоритмов (используются операторы > и <) и они, следовательно, существуют как самоцель. То есть для сравнения разных типов надо бы передавать в такой предикат... сам предикат. Тут без специализации не получится.
Вот как бы пришпандорить обобщение к Вашему коду? Можно имея один из операторов (пусть это будет <) остальной выводить на общих основаниях. Такой подход редко когда не подойдёт.
C++
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
bool ascending(T a, T b)
{
    return a < b;
}
 
template<typename T>
bool descending(T a, T b)
{
    bool non_ascending=!ascending(a,b);
    return (non_ascending && !(non_ascending && !ascending(b,a)));
}
тут в шаблоне descending есть вполне уместное обобщение. Чего не скажешь о ascending.
0
GbaLog-
Любитель чаепитий
3156 / 1462 / 462
Регистрация: 24.08.2014
Сообщений: 5,179
Записей в блоге: 1
Завершенные тесты: 2
21.05.2017, 09:46 #19
DrOffset, внезапно понял, почему у меня ничего таким образом не получалось здесь:
Цитата Сообщение от DrOffset Посмотреть сообщение
C++
1
bubbleSort(arr, size, &descending<int>);
пытался подставить 2 аргумента, как будто в descending 2 шаблонных параметра.
0
Liss29
25 / 14 / 4
Регистрация: 18.11.2012
Сообщений: 567
Завершенные тесты: 1
21.05.2017, 21:11  [ТС] #20
Цитата Сообщение от IGPIGP Посмотреть сообщение
bool non_ascending=!ascending(a,b); //специализация шаблона, так?
* * return (non_ascending && !(non_ascending && !ascending(b,a)));//зачем параметры переставил?
Интересный код, только столько операцй отрицания, что мозг отказывается понимать что к чему зачем параметры в ascending(b,a) поменяли местами? Что бы получить обратный результат?!
0
21.05.2017, 21:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.05.2017, 21:11
Привет! Вот еще темы с решениями:

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

Указатель на функцию в вызове другой функции
Всем доброе утро. У меня есть вот такая функция. double f(double x) { return...

Зачем передавать в функцию X указатель на callback функцию, если последняя ВНЕШНЯЯ и вызовется БЕЗО ВСЯКОГО УКАЗАТЕЛЯ?
Собсно. То есть ребята, вот пример отсюда:...

Передача массива в функцию используя указатель на функцию
У меня имеется готовая программа без передачи функции в функцию указателем, мне...


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

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

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