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

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

06.10.2011, 01:12. Показов 2839. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
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-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru