Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.67
Bers
Заблокирован
#1

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

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

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

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

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

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


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/0ed15c...59469bf21672dc
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.10.2011, 01:12     Помогите разобраться с шаблонами
Посмотрите здесь:

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

Помогите разобраться - C++
У меня есть координаты North,West,East,South. Мне нужно отобразить их на осях ОХ и ОУ. Допустим я ввожу North 5 East 3 South 1 ...

If else помогите разобраться - C++
Доброго времени суток всем. Не так давно начали программировать в C++ MS Visual Studio 2010? и возникло у меня затруднение в работе с if ...

Помогите разобраться с OnClose() - Visual C++
Помогите разобраться! При написании функции OnClose() куда идет сообщение при закрытии окна? где в MFC находится DefWindowProc? Как...

Помогите разобраться с MFC - Visual C++
Никак не могу разобраться с MFC. Выложите пожалуйста, проект, сделанный в vs 2008 с визуальным конструктором, в котором текстбокс и одна...

Помогите разобраться с итераторами - C++
У меня есть шаблон класса контейнер. Я использую vector из stl. Так вот мне нужен итератор для поиска find ( first, last, value ) но...

Помогите разобраться с классами в C++ - C++
Есть задание по ООП С++ Используя классы создать кольцо.Записи кольца включают в себя указатели на очередь, содержащую указатели на на...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
06.10.2011, 01:57     Помогите разобраться с шаблонами #2
конечно, когда задача описана избыточно, это гуд. но не гуд когда через чур.
покажи код который ты хочешь получить.

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

Добавлено через 4 минуты
это -
Цитата Сообщение от Bers Посмотреть сообщение
TIConsole<TConsoleWrapper<adapterName> >::TIConsole()
Цитата Сообщение от Bers Посмотреть сообщение
TIConsole<SystemAdapter>::TIConsole()
специализация для конструктора, а не всего класса.
Bers
Заблокирован
06.10.2011, 01:57  [ТС]     Помогите разобраться с шаблонами #3
Цитата Сообщение от niXman Посмотреть сообщение
конечно, когда задача описана избыточно, это гуд. но не гуд когда через чур.
покажи код который ты хочешь получить.
вот здесь линк иллюстрирующий задачу:
http://liveworkspace.org/code/0ed15c...59469bf21672dc
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 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/3909ad...09289755a6c95f
Bers
Заблокирован
06.10.2011, 02:24  [ТС]     Помогите разобраться с шаблонами #5
Цитата Сообщение от niXman Посмотреть сообщение
специализация для конструктора, а не всего класса.
совершенно верно. Мне нужно получить возможность уточнять отдельные методы как для параметра <клиент>

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

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


http://liveworkspace.org/code/0ed15c...59469bf21672dc

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

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

Мне нужно уточнить метод. Констурктор - это метод. Я уточняю чортов метод.
talis
791 / 543 / 37
Регистрация: 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;
}
Bers
Заблокирован
06.10.2011, 19:34  [ТС]     Помогите разобраться с шаблонами #9
я не фига не понял из этих двух ваших примеров.
Идея уточнения отдельного метода для класса-шаблона, чем параметр ещё не известен, какая?
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
06.10.2011, 19:37     Помогите разобраться с шаблонами #10
Bers, я так понял, что вы хотите сделать специализацию отдельного метода шаблонного класса, не копируя остальную часть этого класса. Или вы другое имели ввиду? Тогда извините, не понял.
Bers
Заблокирован
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
Соотвественно, нужен какой то обходной маневр
talis
791 / 543 / 37
Регистрация: 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>
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.10.2011, 23:50     Помогите разобраться с шаблонами
Еще ссылки по теме:

Помогите разобраться в Наследование - C++
#include&lt;iostream&gt; using namespace std; class Counter1 { protected: int count; public: Counter1():count(0) { }

Vector - помогите разобраться - C++ Linux
Здравствуйте! Помогите нубу разобраться с вектором - потому что я явно чего-то не понимаю с ним. код такой: enum Action_f //это флаг...

Помогите разобраться с xerces - Visual C++
Допустим у меня есть файл index.html. Как открыть, его и получить объект DOM-дерева?

ПОМОГИТЕ РАЗОБРАТЬСЯ В КОДЕ - C++
#include &lt;time.h&gt; #include &lt;conio.h&gt; #include &lt;iostream&gt; #include &lt;assert.h&gt; #include &lt;string.h&gt; #include &lt;stdlib.h&gt; using...

Помогите разобраться с кодом - C++
Код - проверка ввода данных. Если вводиться &quot;x6x&quot;, то вызывается исключение, правильным вводом являются только символы, например: &quot;xxx&quot;,...


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

Или воспользуйтесь поиском по форуму:
stdcout
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()
для всех возможных вариантов. но в этом случае писать много.
Yandex
Объявления
06.10.2011, 23:50     Помогите разобраться с шаблонами
Ответ Создать тему
Опции темы

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