Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
Заблокирован
1

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

06.10.2011, 01:12. Просмотров 2204. Ответов 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
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.10.2011, 01:12
Ответы с готовыми решениями:

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

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

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

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

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

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

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

Добавлено через 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  [ТС] 5
Цитата Сообщение от niXman Посмотреть сообщение
специализация для конструктора, а не всего класса.
совершенно верно. Мне нужно получить возможность уточнять отдельные методы как для параметра <клиент>

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

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


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

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

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

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

Цитата Сообщение от 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  [ТС] 9
я не фига не понял из этих двух ваших примеров.
Идея уточнения отдельного метода для класса-шаблона, чем параметр ещё не известен, какая?
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 19:37 10
Bers, я так понял, что вы хотите сделать специализацию отдельного метода шаблонного класса, не копируя остальную часть этого класса. Или вы другое имели ввиду? Тогда извините, не понял.
0
Заблокирован
06.10.2011, 19:40  [ТС] 11
Цитата Сообщение от talis Посмотреть сообщение
Bers, я так понял, что вы хотите сделать специализацию отдельного метода шаблонного класса, не копируя остальную часть этого класса. Или вы другое имели ввиду? Тогда извините, не понял.
Мне нужен эффект частичной специализации функции-метода.



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

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

Но компилятор на подобную запись сразу же ругнеццо - что ещё не известен тип adapterName
Соотвественно, нужен какой то обходной маневр
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 20:21 12
Если я в этот раз правильно понял, то так. Начните чтение с 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
Сообщений: 210
06.10.2011, 23:50 13
Нужно примерно следующее:
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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.10.2011, 23:50

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

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

ПОМОГИТЕ РАЗОБРАТЬСЯ В JS!
Вот нашел статью...

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

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


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

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

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