| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #120 : 13-04-2009 09:34 »  |  | 
 
 Алгоритм sort реализован ещё в C десятки лет назад. Функция qsort определена в stdlib.h void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *)); Пример из help к Turbo C++ 3.0: #include <stdio.h>#include <stdlib.h>
 #include <string.h>
 
 int sort_function(const void *a, const void *b);
 
 char list[5][4] = { "cat", "car", "cab", "cap", "can" };
 
 int main(void)
 {
 int x;
 qsort((void *)list, 5, sizeof(list[0]), sort_function);
 for (x = 0; x < 5; x++)
 printf("%s\n", list[x]);
 return 0;
 }
 
 int sort_function(const void *a, const void *b)
 {
 return( strcmp((char *)a,(char *)b) );
 }
 Функция сравнения должна возвращать отрицательное число, 0 или положительное число для a<b, a=b и a>b соответственно. |  
						| 
								|  |  
								| « Последнее редактирование: 13-04-2009 09:38 от dimka » |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #121 : 13-04-2009 10:19 »  |  | 
 
 Алексей1153++, проще всего определить независимую функцию (как вариант: статический метод класса) сравнения двух указателей, которая сравнивает то, на что они указывают. Можно отдельным функтором оформить. В качестве параметра передавать, соответственно, функцию или экземпляр функтора.  Не думаю, что переопределение операции сравнения для указателей является лучшим вариантом. В общем, я бы сделал что-то вроде: template<typename Type_>bool compare_val_by_ptr( Type_* left, Type_* right )
 {
 return (*left) < (*right);
 }
 
 //...
 std::vector<int*> vec;
 std::sort(vec.begin(), vec.end(), compare_val_by_ptr<int>);
 
(если подумать, то, наверное, можно и покрасивее) |  
						| 
								|  |  
								| « Последнее редактирование: 13-04-2009 10:37 от Вад » |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #122 : 13-04-2009 11:03 »  |  | 
 
 Вад, ну я для указателей и не переопределял, а только для класса myDWORDp )
 --------
 я там в структуре подправил, не то имел в виду )
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-04-2009 11:38 от Алексей1153++ » |  Записан | 
 
 |  |  | 
	|  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #124 : 25-09-2009 10:49 »  |  | 
 
 как сделать шаблон для генерации типов, инкапсулирующих "простые" типы ? нужно, чтобы получилось нечто вроде (но это спотыкается на объявлении переменных) template<class T,T defaultVal,const char* TXTname>class X
 {
 T m_par;
 
 public:
 
 X()
 {
 m_par=defaultVal;
 }
 
 const T& (operator=) (const T& src)
 {
 m_par=src;
 return m_par;
 }
 
 operator T&()
 {
 return m_par;
 }
 
 const char* GetTextName()
 {
 return TXTname;
 }
 };
 
 //объявление
 X<int,0,"параметр1"> m_1;
 X<CString,"0","параметр2"> m_2;
 X<BYTE,0,"параметр3"> m_3;
 
 //работа с объектом должна происходить точно так же, как будто работаем просто с мембером m_par, например :
 void F()
 {
 CString t;
 t=m_2;
 m_2=t;
 m_2="1111111";
 }
 
компилятор пишет  недопустимое выражение в качестве аргумента шаблона для 'TXTname' |  
						| 
								|  |  
								| « Последнее редактирование: 25-09-2009 11:29 от Алексей1153++ » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #125 : 25-09-2009 14:13 »  |  | 
 
 Параметры шаблона должны быть константами, не могущими изменяться в runtime - аналог макросов, а ты объявляешь указатель char *, для представления которого нужна переменная с хранящимся внутри неё адресом. Кроме того, твой объект не умеет работать с другими такими объектами. Например, ещё надо добавить что-то типа: const X<T>& (operator=) (const X<T>& src){
 m_par=src;
 return m_par;
 }
 Или я не понимаю, как этим пользоваться "прозрачно". |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #126 : 25-09-2009 14:32 »  |  | 
 
 как таки задать строку ещё на этапе компиляции ? Или только через конструктор придётся ?
 А про const X<T>& - это точно , не подумал )) Но если бы в коде встретилась необходимость, дошло бы
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #127 : 25-09-2009 18:29 »  |  | 
 
 Народ на других форумах пишет, что можно передавать только такие строки, которые объявлены в глобальных переменных. Типа template<const char *s>class X {/*...*/};
 
 /* Строковая константа обязательно в глобальной области видимости
 (или namespace), которая не удаляется при завершении какой-нибудь
 функций (даже main). */
 char s[] = "Test";
 
 int main()
 {
 X<s> x;
 }
 |  
						| 
								|  |  
								| « Последнее редактирование: 25-09-2009 18:33 от Dimka » |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #128 : 26-09-2009 03:12 »  |  | 
 
 попробую. Хотя мне это не нравится, лучше затолкну название через конструктор
 Про глобальность тут не совсем всё ясно,  дело в том, что строки вида "строка" и так являются глобальными константами, хотя и и сограниченной видимостью. Специально проверял: если в совершенно различных местах программы встречается выражение "текст" , и текст одинаковый, то указатель выходит одинаковый. То есть компилятор размещает в данных всего одну константную строку и использует указатель при каждом удобном случае.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #129 : 28-09-2009 10:29 »  |  | 
 
 а возможно ли сделать в шаблоне условную компиляцию по типу T ? Навроде
 if(тип T == CString)
 {
 T=T.Left(10);
 }
 else
 {
 }
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #130 : 28-09-2009 10:48 »  |  | 
 
 Ну, скажем, у Александреску есть такой вариант, построенный на специализации шаблона: template <int v>struct IntToType
 {
 enum {value = v };
 };
 
 template <class T, class U>
 struct SameType
 {
 enum { result = false };
 };
 
 template <class T>
 struct SameType<T, T>
 {
 enum {result = true };
 };
 
 // ...
 void Foo(Type& T, IntToType<true>)
 {
 T=T.Left(10);
 }
 
 void Foo(Type&, IntToType<false>)
 {
 }
 
 void Foo(Type& T)
 {
 Foo(T, IntToType<SameType<Type, CString>::result>());
 }
 
Сделал на коленке, не проверял работоспособность    Но принцип примерно такой |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Антон (LogRus) | 
								|  | « Ответ #131 : 28-09-2009 11:04 »  |  | 
 
 Алексей1153++, возможно читаем Вандервуда 15.2 Type Functions =============== 15.2.2 Determining Class Types With the following type function we can determine whether a type is a class type: // traits/isclasst.hpp 
 template<typename T>
 class IsClassT {
 private:
 typedef char One;
 typedef struct { char a[2]; } Two;
 template<typename C> static One test(int C::*);
 template<typename C> static Two test(…);
 public:
 enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
 enum { No = !Yes };
 };
 
This template uses the SFINAE (substitution-failure-is-not-an-error) principle of Section 8.3.1 on page 106. The key to exploit SFINAE is to find a type construct that is invalid for function types but not for other types, or vice versa. For class types we can rely on the observation that the pointer-to-member type construct int C::* is valid only if C is a class type. The following program uses this type function to test whether certain types and objects are class types: // traits/isclasst.cpp 
 #include <iostream>
 #include "isclasst.hpp"
 
 class MyClass {
 };
 
 struct MyStruct {
 };
 
 union MyUnion {
 };
 
 void myfunc()
 {
 }
 
 enumE{e1}e;
 
 // check by passing type as template argument
 template <typename T>
 void check()
 {
 if (IsClassT<T>::Yes) {
 std::cout << " IsClassT " << std::endl;
 }
 else {
 std::cout << " !IsClassT " << std::endl;
 }
 }
 
 // check by passing type as function call argument
 template <typename T>
 void checkT (T)
 {
 check<T>();
 }
 
 int main()
 {
 std::cout << "int: ";
 check<int>();
 
 std::cout << "MyClass: ";
 check<MyClass>();
 
 std::cout << "MyStruct:";
 MyStruct s;
 checkT(s);
 
 std::cout << "MyUnion: ";
 check<MyUnion>();
 
 std::cout << "enum:    ";
 checkT(e);
 
 std::cout << "myfunc():";
 checkT(myfunc);
 }
 
The program has the following output: int:      !IsClassT MyClass:  IsClassT
 MyStruct: IsClassT
 MyUnion:  IsClassT
 enum:     !IsClassT
 myfunc(): !IsClassT
 
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Странно всё это.... |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #132 : 28-09-2009 11:08 »  |  | 
 
 А, я думал, требуется вообще раздельная компиляция. Так-то ничто не мешает просто использовать SameType при ветвлении. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #133 : 28-09-2009 11:37 »  |  | 
 
 Вад, ага, вроде то что то похожее на правду, вот в таком виде подошло: template <int v>
 struct TypesIsSAME
 {
 enum {value = v };
 };
 
 template <class T, class U>
 struct IsTypesSame
 {
 enum { result = false };
 };
 
 template <class T>
 struct IsTypesSame<T, T>
 {
 enum {result = true };
 };
 
 template<class T>
 class X
 {
 void Foo(TypesIsSAME<true>)
 {
 m_par=m_par.Left(10);
 }
 
 void Foo(TypesIsSAME<false>)
 {
 m_par*=1;
 }
 public:
 void Foo()
 {
 TypesIsSAME< IsTypesSame<T, CString>::result > isSame_CString;
 Foo(isSame_CString);
 }
 
 
 
 T m_par;
 };
 
а как не только один тип отличить, а вообще что то вроде свича по типам сделать ? )) (Это не нужно сейчас, но интересно)LogRus , ещё не вник, щас разбираюсь в написанное ) |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #134 : 28-09-2009 11:41 »  |  | 
 
 Вад, кажись понял, можно ведь сделать
 TypesIsSAME< IsTypesSame<T, ТИП>::result > isSame_ТИП;
 
 , только придётся каждую нестандартную функцию делать в двух видах - наполненную и пустую
 
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #135 : 28-09-2009 12:01 »  |  | 
 
 а как не только один тип отличить, а вообще что то вроде свича по типам сделать ? )) (Это не нужно сейчас, но интересно)
 Поскольку программирование в шаблонах чисто функциональное (то есть, там нельзя просто сформировать последовательность действий, в том числе циклы и ветвления), придётся использовать списки типов и построение рекурсивной иерархии типов. Подробно можно почитать про списки типов у того же Александреску, там довольно внятно разбирается   Впрочем, если нужно разделять "один тип - одно действие", и ветвление выполняется в runtime, то достаточно модифицировать подход с SameType. template <class Type>struct TypeToType
 {
 };
 
 
 // ...
 template<class T>
 void Foo(Type&, TypeToType<T>){}
 
 void Foo(Type& T, TypeToType<CString>)
 {
 T=T.Left(10);
 }
 
 void Foo(Type&, TypeToType<CMyClass>)
 {
 }
 
 void Boo(Type& T)
 {
 Foo(T, TypeToType<Type>());
 }
и - да, придётся делать пустую реализацию, если нужен default. |  
						| 
								|  |  
								| « Последнее редактирование: 28-09-2009 12:10 от Вад » |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #136 : 28-09-2009 13:59 »  |  | 
 
 и - да, придётся делать пустую реализацию, если нужен default. 
 причём, для каждого использованного типа ) |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Антон (LogRus) | 
								|  | « Ответ #137 : 29-09-2009 06:57 »  |  | 
 
 Алексей1153++, используй буст   Впрочем, если нужно разделять "один тип - одно действие", и ветвление выполняется в runtime, то достаточно модифицировать подход с SameType.
 фишка в том что переход выполняется в compile time (точнее выкидывается весь не нужный код), т.к. выражение константно так всё я запутался   |  
						| 
								|  |  
								|  |  Записан | 
 
 Странно всё это.... |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #138 : 29-09-2009 07:14 »  |  | 
 
 LogRus, давай распутаю ))  |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #139 : 29-09-2009 07:20 »  |  | 
 
 LogRus, да, ты прав.  Точнее, если Type разный - значит, Boo принадлежит шаблону (или является шаблонной функцией), и будет скомпилировано ровно столько реализаций, сколько нужно, для каждого Type, на самом верхнем уровне вызова   |  
						| 
								|  |  
								| « Последнее редактирование: 29-09-2009 07:24 от Вад » |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #140 : 28-11-2009 17:59 »  |  | 
 
 имеется такой код 	class defaultClass{
 };
 
 
 template<class T=defaultClass>
 class A
 {
 T m_t;
 };
 
можно ли сделать defaultClass безымянным, что-то вроде 	template<class T=class{}>class A
 {
 T m_t;
 };
 
? |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #141 : 01-01-2010 18:20 »  |  | 
 
 ещё вопрос: покажите пример переопределения аллокатора. Не могу даже просто унаследовать, запутался в лабиринтах типов: 		class A{
 };
 
 template<class T>
 class CMyAl:public std::allocator<T>
 {
 
 public:
 template<class _Other>
 struct rebind
 {
 typedef CMyAl<_Other> other;
 };
 
 
 /*
 ...
 */
 };
 
 typedef std::map<int,A,std::less<int>,CMyAl<A> > td_map;
 
 td_map Amap;
 
ошибка error CMyAl<T>::CMyAl(const CMyAl<T> &) throw(): невозможно преобразовать параметр 1 из 'CMyAl<T>' в 'const CMyAl<T> &'...
 ...
 
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #142 : 02-01-2010 00:41 »  |  | 
 
 Он же тебе говорит, хочу копирующий конструктор, так сделай его 	CMyAl(const CMyAl<T> & p) throw() {}CMyAl() throw() {}
ЗЫ (Важно!!!) Да, до кучи... надо 2 раза подумать, прежде чем наследоваться от классов stl, дело в том, что они не имеют виртуальных деструкторов!!! |  
						| 
								|  |  
								| « Последнее редактирование: 02-01-2010 00:44 от lapulya » |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #143 : 02-01-2010 00:55 »  |  | 
 
 Алексей1153++,  можно ли сделать defaultClass безымянным, что-то вроде зачем? |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #144 : 02-01-2010 04:15 »  |  | 
 
 lapulya, да мне пофиг на его деструкторы ) Свой сделаю. А насчёт копирующего - где это написано, я вот так и не понял бы сам Или предлагаешь не наследоваться, а вообще полностью весь код аллокатора содрать и переписать ? зачем?
 занадом )) Ну я уже понял, что нельзя |  
						| 
								|  |  
								| « Последнее редактирование: 02-01-2010 04:20 от Алексей1153++ » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #145 :  02-01-2010 19:16 »   |  | 
 
 да мне пофиг на его деструкторы ) Свой сделаю. Ну ты даёшь, ну ты рискуешь    Ты подумай хорошо, что это означает на самом деле, и насколько аккуратно нужно писать, чтобы не получить утечки памяти. |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #146 : 03-01-2010 00:09 »  |  | 
 
 Алексей1153++, ну для начала, как сказал димка, можно получить утечки. Потом речь идет обо ВСЕХ классах stl (кроме ексепшена вроде), а нетолько об аллокаторе.
 Я бы не наследовался (смысла большого нет), если ты пишешь свой аллокатор, то функции выделения и освобождения памяти ты и так перепишешь, а все остальное там только служебное (конструкторы и деструкторы).
 
 ну а понять, что же компилер говорит, можно так, ты посмотри в то место куда он указывает при ошибке, и увидишь, что он указывает на то место где вызывается копирующий конструктор аллокатора, вот компиллер и говорит, что ну нет подходящего (тот что есть не подходит)
 |  
						| 
								|  |  
								| « Последнее редактирование: 03-01-2010 00:16 от lapulya » |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #147 : 03-01-2010 02:52 »  |  | 
 
 да мне пофиг на его деструкторы ) Свой сделаю. Ну ты даёшь, ну ты рискуешь    Ты подумай хорошо, что это означает на самом деле, и насколько аккуратно нужно писать, чтобы не получить утечки памяти.слова, слова... На примере бы показал ) Над чем трясётесть то Ну, то есть, наследоваться не стОит, а просто скопировать интерфейс и переписать ? |  
						| 
								|  |  
								| « Последнее редактирование: 03-01-2010 02:54 от Алексей1153++ » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #148 : 03-01-2010 03:48 »  |  | 
 
 Алексей1153++, и когда ты матчасть выучишь... Ну попробуй запусти нижеследующее. Не знаю, что быстрее случится: core dump или ты Ctrl-C нажать успеешь... class A{
 private:
 int *data;
 public:
 A():
 data(new int[1000000])
 {
 }
 ~A()
 {
 delete[] data;
 }
 };
 
 class B:
 public A
 {
 private:
 int *anotherData;
 public:
 B():
 A(), anotherData(new int[1000000])
 {
 }
 ~B()
 {
 delete[] anotherData;
 }
 };
 
 int main()
 {
 for(;;)
 {
 A *a = new B();
 delete a;
 }
 return 0;
 }
 В этом вся разница между виртуальным и невиртуальным деструкторами в суперклассе. |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #149 : 03-01-2010 04:32 »  |  | 
 
 Дык я знаю разницу между виртуальным и не виртуальным деструктором, только к данному случаю то это какое отношение   А  "Ctrl-C" - это о чём ? У мну в студии нет такого сочетания ) |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	|  |