Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 10.10.2015
Сообщений: 5

Как можно изменить параметр шаблона (template)?

15.12.2015, 21:26. Показов 2664. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
есть такие классы:
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
class abstract
{
public:
    virtual int method() = 0; // Допустим
};
 
class A:
    public abstract
{
    int number_int; 
public:
    A() {}
    int method()
    {
        return -1; // Допустим
    }
 
};
 
class B:
    public abstract
{
    float number_float = 5.5; // Допустим
public:
    B() {}
    int method()
    {
        return (number_float + 1) / 2;
    }
};
 
template < class T >
class general
{
    float number_general;
    T object;
public:
    general(int a) : object()
    {
        number_general = a;
    }
    int sum()
    {
        number_general += object.method();
        return number_general;
    }
};
 
int main()
{
    int num = 0;
    cin >> num;
    switch (num)
    {
    case 1: general<A> new_class(5); break; // 1
    case 2: general<B> new_class(5); break; // 2
    default:
        break;
    }
    cout << new_class.sum() << endl;
    system("pause");
    return 0;
}
и вопрос:
т.к. в таком случае (switch) будет ошибка (не будет инициализирован объект), то как сделать так, чтобы в зависимости от выбранного условия, создавался объект с заданными параметрами?

можно было предположить создание указателя:
C++
1
2
3
4
5
6
7
8
switch (num)
    {
    case 1: new_class  = new A(); break; // 1
    case 2: new_class  = new B(); break; // 2
    default:
        break;
    }
general<*new_class> newnew_class(5);
но это точно неправильно
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.12.2015, 21:26
Ответы с готовыми решениями:

Можно ли использовать параметр шаблона без типа?
#define TV(OBJ) typeof(OBJ), OBJ template&lt;class T, T obj&gt; class A {/*...*/}; int f (int); A&lt;TV(f)&gt; a; Можно ли сделать...

Передача функции как параметр шаблона
Хочу передавать в шаблон любую функцию без параметров и вызывать ее из него. Как это сделать? Не работает, но примерно так должно...

Свой тип как параметр шаблона
Есть вопрос по коду: #include &lt;iostream&gt; #include &lt;memory&gt; #include &lt;vector&gt; using namespace std; template&lt;class T&gt; ...

4
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
15.12.2015, 22:17
Ну, самое простое что в голову приходит, это делать нужную работу внутри веток case:
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
template <typename T>
int work(general<T>& gnr)
{
    return gnr.sum();
}
 
int main()
{
    int num = 0;
    cin >> num;
    switch (num)
    {
    case 1:
    {
        general<A> new_class(5);
        cout << work(new_class) << endl;
        break;
    }
    case 2:
    {
        general<B> new_class(5);
        cout << work(new_class) << endl;
        break;
    }
    default:
        break;
    }
}
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
15.12.2015, 22:24
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
#include <iostream>
 
class T_abstract
{
public:
    virtual int method() = 0; 
};
 
class A:
    public T_abstract
{
    int number_int; 
public:
    A() {}
    int method()
    {
        std::cout   <<  'A'
                    <<  std::endl;
        return -1; 
    }
 
};
 
class B:
    public T_abstract
{
    float number_float = 5.5; 
public:
    B() {}
    int method()
    {
        std::cout   <<  'B'
                    <<  std::endl;
 
        return (number_float + 1) / 2;
    }
};
 
template < class T >
class T_general
{
    float number_general;
    T object;
public:
    T_general(int a) : object()
    {
        number_general = a;
    }
    int sum()
    {
        number_general += object.method();
        return number_general;
    }
};
 
int main()
{
    char    let     =   0;
 
    for(;;)
    {
        std::cout   <<  std::endl
                    <<  "let = ";
        std::cin    >>  let;
 
        std::cout   <<  (
                            let     ==  'a'
                                ?   T_general<A>(5).sum()
                                :   T_general<B>(5).sum()
                        ) 
        
                    << std::endl;
    }//for
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.12.2015, 23:49
Лучший ответ Сообщение было отмечено AAANDREW как решение

Решение

Цитата Сообщение от AAANDREW Посмотреть сообщение
и вопрос:
т.к. в таком случае (switch) будет ошибка (не будет инициализирован объект), то как сделать так, чтобы в зависимости от выбранного условия, создавался объект с заданными параметрами?

наиболее оптимальным вариантом было бы пересмотреть дизайн решения.
потому что ваша проблема легко устраняется простыми способами
например, как это показал господин DiffEreD в сообщении #2
тогда проблема исчезнет сама собой.

но если вам критично максимально следовать указанному вами дизайну,
тогда вам может быть сможет помочь паттерн type erasure:

http://rextester.com/DUME68820

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
#include <iostream>
 
class A  // наследоваться от интерфейса не нужно
{
    int number_int; 
public:
    int method()const { return -1; }
};
 
class B
{
    float number_float = 5.5; 
public:
    int method()const { return (number_float + 1) / 2; }
};
 
 
// времени компиляции 
// вычисляем максимальный размер
// указанных типов
template<class A, class B> class max_size
{
    static const size_t sizeA = sizeof(A);
    static const size_t sizeB = sizeof(B);
public:
    static const size_t size = sizeA > sizeB ? sizeA : sizeB;
};
 
 
// не шаблонный!
class general
{
    // паттерн type erasure
    // суть в том, что есть не шаблонный интерфейс
    
    struct ihelper
    {
        virtual ~ihelper(){}
        virtual int sum() = 0;
    };
    
    
    // и шаблонный наследник
    // дергая не шаблонный интерфейс
    // мы приводим в действие функции шаблоно-наследника
    template <class T>
    struct helper : ihelper
    {
        helper(const int a)
            : number_general(a)
        {}
        
        virtual int sum() 
        {
            number_general += object.method();
            return number_general;
        }
        
        float number_general;
        T object;
    };
    
    
    // теперь резервируем буфер под будущего наследника
    // для этого рассчитываем оптимальный размер памяти
    // который может понадобится для его хранения
    enum { size = max_size<helper<A>, helper<B> >::size };
 
    // в качесте этого буфера
    // будем использовать обычный массив
    char type_erasure[ size ];
    
public:
 
       
    // данная функция порождает нужного нам наследника
    // аллоцируя его в нашем буфере
    template<class T> void make(const int a)
    {
        // убедимся, что наш массив достаточно большой
        // что бы вместить в себя наследника
        static_assert(
            sizeof(helper<T>) <= size,
            "ERROR: size helper too big"
        );
        
        // сообщаем, что хотим создать объект
        // не в куче, а в указанном хранилище
        new (type_erasure) helper<T>(a);
    }    
    
    
    // подсчитывает сумму
    int sum()
    {
        // на самом деле она лишь делегирует эту задачу наследнику
        // который сделает для нас всю грязную работу
        
        // но для этого нужно сначала извлечь наследника из нашего буфера
        // в рантайме мы не знаем его точного типа
        // но мы знаем про его не шаблонный интерфейс
        auto* help = reinterpret_cast<ihelper*>(type_erasure);
        
        //и через этот интерфейс можем привести наследника в действие
        return help->sum();
    }
 
    // теперь нам нужен диструктор
    // что бы корректно освободить все захваченные наследником ресурсы
    ~general()
    {
        // для этого извлекаем наследника
        // через его интерфейс
        auto* help = reinterpret_cast<ihelper*>(type_erasure);
        
        // и явным образом дергаем его виртуальный диструктор
        // так как диструктор виртуальный
        // то это приведет к запуску диструктора наследника
        // и тот корректно почистит все за собой
        help->~ihelper();
    }
 
    
};
 
 
// пример использованеия паттерна:
void example_pattern(const int num)
{
    // больше не шаблонный
    general example;
    
    switch (num)
    {
        // теперь в зависимости от 
        // захватываем ресурс: A или B указав стартовые параметры
        case 1: example.make<A>(5); break; 
        case 2: example.make<B>(5); break; 
    }
    
    // и теперь спокойно подсчитываем сумму
    std::cout << "результат для num = "<< num 
        << " : " << example.sum() << "\n";
}
 
int main()
{
    std::cout
        <<"добрый вечер, AAANDREW\n"
        <<"вам может помочь паттерн 'type erasure'\n";
    
    
    example_pattern(1);
    example_pattern(2);
    
}
5
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
16.12.2015, 03:56
немного не по сабжу: а в основе boost.variant тоже type erasure? если кто знает
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.12.2015, 03:56
Помогаю со студенческими работами здесь

Шаблоннный клас как параметр шаблона
Если в кратце: Имеется такой код: typedef ByteStuffing&lt;USART0, CRC8&lt;USART0&gt; &gt; StreamDelimiter; В шаблоне CRC8 тип всегда должен...

Передать шаблонный класс, как параметр шаблона
нужно не используя stl написать аналог класса list. написал болванку и застрял template&lt;class C&gt; class node{ protected: C...

Результат работы функции как параметр шаблона
В старом с++ билдере такое работало, новый clang ругается. template &lt;class T, const IID* piid = &amp;__uuidof(T)&gt; class CComQIPtr { ...

Зачем нужен шаблон как параметр шаблона?
Видел много примеров, но что-то не особо понятно зачем и как это работает.

Указатель на статический массив как параметр шаблона
Добрый день. Необходимо параметр шаблона сделать указателем и передавать в него указатель на статический массив: template&lt;size_t...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru