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

Помогите разобраться с шаблонами

06.10.2011, 01:12. Показов 2887. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пытаюсь реализовать новую для себя методику "службы класса".
Все хорошо работало, пока не возникла необходимость в качестве клиента слжбы задействовать не обычный класс, а класс-шаблон.

Впрочем, все по порядку...

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

Здесь линк на более удобный пастербин:
http://liveworkspace.org/code/... 8e3ba689eb


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
//Служба - свойство класса, инструмент, обслуживающий какие либо
 внутренние потребности класса в чем либо.
//Пример1 - обработка ошибок/исключительных ситуаций, с которыми может столкнуться класс
//Пример2 - что бы любой класс сделать синглтоном, достаточно унаследовать это свойство от специальной службы "синглтон"
 
//методика организации служб
//Основной Принцип работы Службы:
 
// class Клиент: public Служба<Клиент>
// {};
 
//Точная ручная настройка работы службы с самыми нестандартными клиентами 
//достигается за счёт уточнений методов клужбы для конкретного клиента
//В особых ситуациях всегда можно полностью уточнить сам класс службы, а не только отдельные его методы
//Для схожих классов можно использовать дефолтные реализации
//Это напоминает молиформизм, только статический, времени компиляции.
 
//Но есть проблемма. Если класс клиент - сам является шаблоном...
 
// template<Адаптер>
// class Клиент: public Служба< Клиент<адаптер> >
// {};
 
//Проблемма в том, что чтобы уточнять методы службы, необходимо 
//к этому моменту уже знать точное значение параметра <адаптер>
 
// Мне необходимо придумать способ, как можно уточнять отельные методы службы, 
// для всего параметра службы Клиент<адаптер>, 
// не зная при этом, какой конкретнвй адаптер будит использован
 
// Насколько мне известно, это называется "частичная специализация". И что частично специализировать функцию - нельзя
// Однако, наверняка существуют обходные пути...
 
// Ниже представленный код - не рабочий. У меня просто уже плавятся мозги от этих шаблонов. 
// Возможно ошибка там довольно простая
 
 
#include <typeinfo>
#include <iostream>
#include "GlobDefines.h"
 
#define MESSAGE(text1, ClassName, text2) std::cout<< text1<< typeid(ClassName() ).name()<<text2<<std::endl;
 
//описание службы
template<class className>
class TIConsole
{ 
public:
    TIConsole(){ ConstructorFalse(); } //Защита от дурака.
    //Не существует тела функции ConstructorFalse
    //Попытка вызвать такой конструктор приведёт к ошибке компиляции
    //Каждый класс-клиент первым делом уточнит конструктор службы, 
    //и в этой уточненной версии не произойдёт вызова этой функции
 
    //Таким образом службу можно создавать только для конкретных классов-клиентов
    //запихать в качестве параметра службы все что угодно уже не получится
    
    void PrintText() {  MESSAGE("Запущен метод TIConsole<", className, ">::PrintText()"); }
protected:
    void ConstructorFalse(); //попытка вызвать этот метод приведёт к ошибке компиляции
    void ConstructorTrue() { MESSAGE("Разрешение на создание экземпляра класса TIConsole<", className, "> полученно"); }
};
 
//уточненное описание класс TIConsole специально расчитанное на то, 
//что бы можно было в качества параметра шаблона передавать не просто класс, а шаблонн. 
//создавать объекты типа TIConsole< Шаблон<тип>  >
template<  class adapterName, template<class adapterName> class className >
class TIConsole< className<adapterName> >:public TIConsole<adapterName>
{ 
public: 
    //на эту строчку укажет компилятор сигнализируя об ошибке, которую я пытаюсь устранить
    //Причина ошибки - ниже.
    TIConsole() { MESSAGE("Запущен конструктор TIConsole<", className<adapterName>, " >"); }
};
 
//описание враппера
template<class adapterName>
class TConsoleWrapper:public TIConsole< TConsoleWrapper<adapterName> >
{ 
public:    
    TConsoleWrapper() {   ConstructorFalse(); } //Защита от дурака.
};
 
//уточнение враппера
template <>
TConsoleWrapper<SystemAdapter>::TConsoleWrapper() 
{ 
    MESSAGE("Переопределяю конструктор TConsoleWrapper<", SystemAdapter, ">");
    ConstructorTrue(); //получает разрешение на использование конструктора 
    //только для конкретного параметров шаблона SystemAdapter
}
 
//уточнение TIConsole для враппера
template<  class adapterName, template<class adapterName> class TConsoleWrapper >
TIConsole<TConsoleWrapper<adapterName> >::TIConsole() 
{ 
    //Смысл уточнения: 
    //TIConsole<TConsoleWrapper<adapterName> > должен получить разрешение на использование 
    //конструктора независимо от парметра шаблона adapterName
    ConstructorTrue(); 
    MESSAGE("Переопределяю конструктор TIConsole<", TConsoleWrapper<adapterName>, ">");
    //Ошибка компилятора:
    //error C2995: TIConsole<className<adapterName>>::TIConsole(void): шаблон функции уже определен
    //Помогите найти ошибку!
}
 
//Этот пример иллюстрирует как получать разрешения на использование конструктора
//для не шаблонных параметров TIConsole
//А данном случае разрешение будит полученно для клиента службы - SystemAdapter
template <>
TIConsole<SystemAdapter>::TIConsole() 
{ 
    ConstructorTrue(); 
    MESSAGE("Переопределяю конструктор TIConsole<", SystemAdapter, ">");
}
 
 
 
 
 
int main (void)
{
    using namespace std;
    TConsoleWrapper<SystemAdapter> my;
 
    EndProgramm();
}
Добавлено через 3 часа 25 минут
вот здесь линк иллюстрирующий задачу:
http://liveworkspace.org/code/... 9bf21672dc
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.10.2011, 01:12
Ответы с готовыми решениями:

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

Разобраться с вложенными классами-шаблонами
Есть код (Стивен Дьюхерст, С++ священные знания): template &lt;class T&gt; class AnAlloc { public: //... template...

Разобраться с шаблонами joomla 1.5
Добрый день, есть index.php как я понял с несколькими шаблонами для страниц сайта, вот только не могу разобраться как подключить...

12
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
06.10.2011, 01:57
конечно, когда задача описана избыточно, это гуд. но не гуд когда через чур.
покажи код который ты хочешь получить.

Добавлено через 21 секунду
т.е. то, какого использования кода ты ожидаешь.

Добавлено через 4 минуты
это -
Цитата Сообщение от Bers Посмотреть сообщение
TIConsole<TConsoleWrapper<adapterName> >::TIConsole()
Цитата Сообщение от Bers Посмотреть сообщение
TIConsole<SystemAdapter>::TIConsole()
специализация для конструктора, а не всего класса.
0
Заблокирован
06.10.2011, 01:57  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
конечно, когда задача описана избыточно, это гуд. но не гуд когда через чур.
покажи код который ты хочешь получить.
вот здесь линк иллюстрирующий задачу:
http://liveworkspace.org/code/... 9bf21672dc
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
06.10.2011, 02:02
линк порезанный.

Добавлено через 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
#include <iostream>
 
template<char ch>
struct key_processor;
 
template<>
struct key_processor<'c'> {
   void m() { std::cout << 'c' << std::endl; }
};
template<>
struct key_processor<'f'> {
   void m() { std::cout << 'f' << std::endl; }
};
template<>
struct key_processor<'i'> {
   void m() { std::cout << 'i' << std::endl; }
};
 
int main() {
   key_processor<'c'>().m();
   key_processor<'f'>().m();
   // key_processor<'j'>().m(); // error: invalid use of incomplete type 'struct key_processor<'j'>'
}
http://liveworkspace.org/code/... 9755a6c95f
0
Заблокирован
06.10.2011, 02:24  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
специализация для конструктора, а не всего класса.
совершенно верно. Мне нужно получить возможность уточнять отдельные методы как для параметра <клиент>

так и для параметра <Клиент<параметр_клиента> >

причем, нельзя ж просто так выполнить частичную специализацию функции....


http://liveworkspace.org/code/... 9bf21672dc

Добавлено через 22 минуты
так и для параметра <Клиент<параметр_клиента> >

где параметр_клиента - параметр шаблона, и ещё пока не известен
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
06.10.2011, 17:05
Цитата Сообщение от Bers Посмотреть сообщение
совершенно верно. Мне нужно получить возможность уточнять отдельные методы как для параметра <клиент>
так и для параметра <Клиент<параметр_клиента> >
так а специализация только лишь конструктора тут при чем?
0
Заблокирован
06.10.2011, 17:07  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
так а специализация только лишь конструктора тут при чем?
не понял вопроса.

Мне нужно уточнить метод. Констурктор - это метод. Я уточняю чортов метод.
0
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 19:28
Если я вас правильно понял, то

Цитата Сообщение от http://www.cplusplus.com/doc/tutorial/templates/
When we declare specializations for a template class, we must also define all its members, even those exactly equal to the generic template class, because there is no "inheritance" of members from the generic template to the specialization.
Так что, только уточнять весь класс. Однако, можно так:

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>
#include <iomanip>
#include <string>
#include <typeinfo>
 
template <typename T>
class printer
{
protected:
    T obj;
 
public:
    printer( const T &_obj ) : obj( _obj ){};
 
    void print( std::ostream & os )
    {
        os << typeid( *this ).name() << ":\t" << obj << '\n';
    }
};
 
 
class b_printer : public printer <bool>
{
public:
    b_printer( const bool &_obj ) : printer( _obj ){};
 
    void print( std::ostream & os )
    {
        os << typeid( *this ).name() << ":\t" << std::boolalpha << obj << '\n';
    }
};
 
 
int main()
{
    printer< std::string > str_printer( "String data" );
    printer< double > dbl_printer( 248.124 );
    printer< char > char_printer( 'v' );
    printer< bool > bool_1_printer( true );
    b_printer bool_0_printer( false );
 
    str_printer.print( std::cout );
    dbl_printer.print( std::cout );
    char_printer.print( std::cout );
    bool_1_printer.print( std::cout );
    bool_0_printer.print( std::cout );
 
    return 0;
}
Добавлено через 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
#include <iostream>
#include <iomanip>
#include <string>
#include <typeinfo>
 
template <typename T>
class printer
{
protected:
    T obj;
 
public:
    printer( const T &_obj ) : obj( _obj ){};
 
    void print( std::ostream & os );
};
 
template <typename T>
void printer<T>::print( std::ostream & os )
{
    os << typeid( *this ).name() << ":\t" << obj << '\n';
}
 
// закомментируйте эту специализацию, чтобы увидеть разницу
template <>
void printer<bool>::print( std::ostream & os )
{
    os << typeid( *this ).name() << ":\t";
 
    if( obj )
       os << "hell yeah!\n";
    else
       os << "no way!\n";
}
 
 
int main()
{
    printer< std::string > str_printer( "String data" );
    printer< double > dbl_printer( 248.124 );
    printer< char > char_printer( 'v' );
    printer< bool > bool_1_printer( true );
    printer< bool > bool_0_printer( false );
 
    str_printer.print( std::cout );
    dbl_printer.print( std::cout );
    char_printer.print( std::cout );
    bool_1_printer.print( std::cout );
    bool_0_printer.print( std::cout );
 
    return 0;
}
0
Заблокирован
06.10.2011, 19:34  [ТС]
я не фига не понял из этих двух ваших примеров.
Идея уточнения отдельного метода для класса-шаблона, чем параметр ещё не известен, какая?
0
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 19:37
Bers, я так понял, что вы хотите сделать специализацию отдельного метода шаблонного класса, не копируя остальную часть этого класса. Или вы другое имели ввиду? Тогда извините, не понял.
0
Заблокирован
06.10.2011, 19:40  [ТС]
Цитата Сообщение от talis Посмотреть сообщение
Bers, я так понял, что вы хотите сделать специализацию отдельного метода шаблонного класса, не копируя остальную часть этого класса. Или вы другое имели ввиду? Тогда извините, не понял.
Мне нужен эффект частичной специализации функции-метода.



Мне нужно сделать что-то вроде:

C++
1
2
3
4
5
6
     template <>
     TIConsole<TConsoleWrapper<adapterName> >::TIConsole() 
     { 
         ConstructorTrue();  MESSAGE("Переопределяю конструктор TIConsole<",   
         TConsoleWrapper<adapterName>, ">");
     }

Но компилятор на подобную запись сразу же ругнеццо - что ещё не известен тип adapterName
Соотвественно, нужен какой то обходной маневр
0
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 20:21
Если я в этот раз правильно понял, то так. Начните чтение с 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
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
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <typeinfo>
 
//-------------- адаптер --------------
template <typename X>
class default_adapter
{
public:
    void out( std::ostream & os, X & obj );
};
 
template <typename X>
void default_adapter<X>::out( std::ostream & os, X & obj )
{
    os << obj;
}
 
// специализация адаптера для vector<int>
template <>
void default_adapter< std::vector<int> >::out( std::ostream & os, std::vector<int> & obj )
{
    os << "specialization for <std::vector<int> >:";
    for( std::vector<int>::iterator it = obj.begin(); it != obj.end(); it++ )
        os << ' ' << *it << ';';
}
 
//------------ принтер ------------------
 
                      /*              параметр шаблона объявлен до шаблона  */
template < typename T, typename X = T, class adapter_t = default_adapter< X > >
class printer
{
protected:
    T obj;
    adapter_t adapter;
 
public:
    printer( const T &_obj, const adapter_t &_adapter = adapter_t() ) : obj( _obj ), adapter( _adapter ) {};
 
    void print( std::ostream & os )
    {
        adapter.out( os, obj );
        os << '\n';
    }
};
 
// специализация для printer<float, int, default_adapter<int> >
template <>
void printer< float, int >::print( std::ostream & os )
{
    os << "specialization for <float, int>: ";
    int val = obj;
    adapter.out( os, val );
    os << '\n';
}
 
 
int main()
{
    std::cout << "printer<std::string>: ";
    // строка в качестве T
    // использует обычные шаблоны
    printer< std::string > str_printer( "String data" );
    str_printer.print( std::cout );
 
    //------------------------
 
    std::cout << "printer< std::vector<int> >: ";
 
    std::vector<int> int_vec;
    int_vec.push_back( 8 );
    int_vec.push_back( 16 );
    int_vec.push_back( 32 );
 
    // vector<int> в качестве T
    // испольует специализацию адаптера для vector<int>
    printer< std::vector<int> > vector_printer( int_vec );
 
    vector_printer.print( std::cout );
 
    //------------------------
 
    std::cout << "printer< float, int, default_adapter<int> >: ";
 
    // принтер float, но использует default_adapter<int>
    // (так как второй параметр - int)
    printer<float, int> weird_printer( 3.14f );
    weird_printer.print( std::cout );
 
    //-------------------------
 
    std::cout << "printer< float, int, default_adapter<float> >: ";
 
    // использует default_adapter<float>, так как это явно указано.
    // второй параметр, int, игнорируется
    printer<float, int, default_adapter<float>> normal_printer( 3.14f );
    normal_printer.print( std::cout );
 
    return 0;
}
Добавлено через 2 минуты
Объект printer<float, int> weird_printer использует специализацию. int означает, что в качестве адаптера будет default_adapter<int>
1
53 / 53 / 2
Регистрация: 06.04.2011
Сообщений: 209
06.10.2011, 23:50
Нужно примерно следующее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class T>
class A {};
 
template<class T>
class XXX
{
public:
    void foo() { std::cout << "T != A<SomeType>" << std::endl; }
};
 
template<>
void XXX<template<class T> class A>::foo()
{
    std::cout << "T == A<SomeType>" << std::endl;
}
то есть нужно, чтобы при параметре шаблона класса XXX, отличном от любого экземпляра шаблонного класса A, метод foo "вёл" себя одним образом, а при параметре шаблона, являющимся одним из экземпляров шаблонного класса A, другим.
Это можно сделать правильно, чтобы компилировалось, если вместо
C++
1
2
template<>
void XXX<template<class T> class A>::foo()
писать
C++
1
2
template<>
void XXX<A<Type_N> >::foo()
для всех возможных вариантов. но в этом случае писать много.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.10.2011, 23:50
Помогаю со студенческими работами здесь

Помогите разобраться.
Ребята, у меня проблема: Когда я обновляю информацию на сайте (размещаю статью, добавляю пользователя, меняю пароль) - изменения видны...

помогите разобраться!
пару месяцев или месяц назад случилось ЧП. изображение на сайте с тИЦами неплохого количества резко обнулилось. А по ссылке на эту...

ПОМОГИТЕ РАЗОБРАТЬСЯ В JS!
Вот нашел статью https://**********************/questions/620830/Изменение-содержимого-сайта-с-помощью-расширения-chrome .Хочу сделать...

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

Помогите разобраться
Есть сайт www.ivrose.ru что то с ним делали ребята по раскрутке, сайт начал идти в гору, добрался по двум запросам до 100 места и рухнул в...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru