Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 3 4 [5] 6   Вниз
  Печать  
Автор Тема: борьба с шаблонами  (Прочитано 132200 раз)
0 Пользователей и 6 Гостей смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #120 : 13-04-2009 09:34 » 

Алгоритм sort реализован ещё в C десятки лет назад.

Функция qsort определена в stdlib.h
Код: (C++)
void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));

Пример из help к Turbo C++ 3.0:
Код: (C++)
#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 » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #122 : 13-04-2009 11:03 » 

Вад, ну я для указателей и не переопределял, а только для класса myDWORDp )

--------
я там в структуре подправил, не то имел в виду )
« Последнее редактирование: 13-04-2009 11:38 от Алексей1153++ » Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #123 : 14-04-2009 03:36 » 

я бы сделал вот так Улыбаюсь

Использование Boost Pointer Container Library: http://blog.alno.name/2009/04/using-boost-ptr-containers/
« Последнее редактирование: 14-04-2009 03:38 от LogRus » Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #125 : 25-09-2009 14:13 » 

Параметры шаблона должны быть константами, не могущими изменяться в runtime - аналог макросов, а ты объявляешь указатель char *, для представления которого нужна переменная с хранящимся внутри неё адресом.

Кроме того, твой объект не умеет работать с другими такими объектами. Например, ещё надо добавить что-то типа:
Код: (C++)
const X<T>& (operator=) (const X<T>& src)
{
        m_par=src;
        return m_par;
}

Или я не понимаю, как этим пользоваться "прозрачно".
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #126 : 25-09-2009 14:32 » 

как таки задать строку ещё на этапе компиляции ? Или только через конструктор придётся ?

А про const X<T>& - это точно , не подумал )) Но если бы в коде встретилась необходимость, дошло бы
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #127 : 25-09-2009 18:29 » 

Народ на других форумах пишет, что можно передавать только такие строки, которые объявлены в глобальных переменных. Типа

Код: (C++)
template<const char *s>
class X {/*...*/};

/* Строковая константа обязательно в глобальной области видимости
   (или namespace), которая не удаляется при завершении какой-нибудь
   функций (даже main). */

char s[] = "Test";

int main()
{
  X<s> x;
}

« Последнее редактирование: 25-09-2009 18:33 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #128 : 26-09-2009 03:12 » 

попробую. Хотя мне это не нравится, лучше затолкну название через конструктор

Про глобальность тут не совсем всё ясно,  дело в том, что строки вида "строка" и так являются глобальными константами, хотя и и сограниченной видимостью. Специально проверял: если в совершенно различных местах программы встречается выражение "текст" , и текст одинаковый, то указатель выходит одинаковый. То есть компилятор размещает в данных всего одну константную строку и использует указатель при каждом удобном случае.
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #129 : 28-09-2009 10:29 » 

а возможно ли сделать в шаблоне условную компиляцию по типу T ? Навроде

if(тип T == CString)
{
   T=T.Left(10);
}
else
{
}
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #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
Записан

Странно всё это....
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #132 : 28-09-2009 11:08 » 

А, я думал, требуется вообще раздельная компиляция. Так-то ничто не мешает просто использовать SameType при ветвлении.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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, ещё не вник, щас разбираюсь в написанное )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #134 : 28-09-2009 11:41 » 

Вад, кажись понял, можно ведь сделать

TypesIsSAME< IsTypesSame<T, ТИП>::result > isSame_ТИП;

, только придётся каждую нестандартную функцию делать в двух видах - наполненную и пустую
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #136 : 28-09-2009 13:59 » 

Цитата
и - да, придётся делать пустую реализацию, если нужен default.
причём, для каждого использованного типа )
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #137 : 29-09-2009 06:57 » 

Алексей1153++, используй буст Улыбаюсь

Впрочем, если нужно разделять "один тип - одно действие", и ветвление выполняется в runtime, то достаточно модифицировать подход с SameType.

фишка в том что переход выполняется в compile time (точнее выкидывается весь не нужный код), т.к. выражение константно

так всё я запутался Улыбаюсь
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #138 : 29-09-2009 07:14 » 

LogRus, давай распутаю ))
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #139 : 29-09-2009 07:20 » 

LogRus, да, ты прав.
Точнее, если Type разный - значит, Boo принадлежит шаблону (или является шаблонной функцией), и будет скомпилировано ровно столько реализаций, сколько нужно, для каждого Type, на самом верхнем уровне вызова Улыбаюсь
« Последнее редактирование: 29-09-2009 07:24 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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;
};

?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #141 : 01-01-2010 18:20 » new

ещё вопрос: покажите пример переопределения аллокатора. Не могу даже просто унаследовать, запутался в лабиринтах типов:
Код:
		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
Молодой специалист

ru
Offline 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
Молодой специалист

ru
Offline Offline

« Ответ #143 : 02-01-2010 00:55 » 

Алексей1153++,
Цитата
можно ли сделать defaultClass безымянным, что-то вроде
зачем?
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #144 : 02-01-2010 04:15 » 

lapulya, да мне пофиг на его деструкторы ) Свой сделаю. А насчёт копирующего - где это написано, я вот так и не понял бы сам

Или предлагаешь не наследоваться, а вообще полностью весь код аллокатора содрать и переписать ?

Цитата
зачем?
занадом )) Ну я уже понял, что нельзя
« Последнее редактирование: 02-01-2010 04:20 от Алексей1153++ » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #145 : 02-01-2010 19:16 » 

Цитата: Алексей1153++
да мне пофиг на его деструкторы ) Свой сделаю.
Ну ты даёшь, ну ты рискуешь Ага Ты подумай хорошо, что это означает на самом деле, и насколько аккуратно нужно писать, чтобы не получить утечки памяти.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #146 : 03-01-2010 00:09 » 

Алексей1153++, ну для начала, как сказал димка, можно получить утечки. Потом речь идет обо ВСЕХ классах stl (кроме ексепшена вроде), а нетолько об аллокаторе.

Я бы не наследовался (смысла большого нет), если ты пишешь свой аллокатор, то функции выделения и освобождения памяти ты и так перепишешь, а все остальное там только служебное (конструкторы и деструкторы).

ну а понять, что же компилер говорит, можно так, ты посмотри в то место куда он указывает при ошибке, и увидишь, что он указывает на то место где вызывается копирующий конструктор аллокатора, вот компиллер и говорит, что ну нет подходящего (тот что есть не подходит)
« Последнее редактирование: 03-01-2010 00:16 от lapulya » Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #147 : 03-01-2010 02:52 » 

Цитата: Алексей1153++
да мне пофиг на его деструкторы ) Свой сделаю.
Ну ты даёшь, ну ты рискуешь Ага Ты подумай хорошо, что это означает на самом деле, и насколько аккуратно нужно писать, чтобы не получить утечки памяти.
слова, слова... На примере бы показал ) Над чем трясётесть то

Ну, то есть, наследоваться не стОит, а просто скопировать интерфейс и переписать ?
« Последнее редактирование: 03-01-2010 02:54 от Алексей1153++ » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #148 : 03-01-2010 03:48 » 

Алексей1153++, и когда ты матчасть выучишь...

Ну попробуй запусти нижеследующее. Не знаю, что быстрее случится: core dump или ты Ctrl-C нажать успеешь...
Код: (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;
}
В этом вся разница между виртуальным и невиртуальным деструкторами в суперклассе.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #149 : 03-01-2010 04:32 » 

Дык я знаю разницу между виртуальным и не виртуальным деструктором, только к данному случаю то это какое отношение Улыбаюсь

А  "Ctrl-C" - это о чём ? У мну в студии нет такого сочетания )
Записан

Страниц: 1 2 3 4 [5] 6   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines