Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с переопределением операций в шаблоне 
V
    Опции темы
astakor
  Дата 19.6.2012, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 19.6.2012

Репутация: нет
Всего: нет



Доброго всем времени суток! smile

Возникла необходимость написать код, где шаблон структуры данных – двусвязный циклический список, содержащий статический массив указателей на объекты. Также надо переопределить операции сравнения включаемых объектов.

Вот в этом пункте и возникли проблемы.

Собственно, код:

Код

#include <stdlib.h>

//Размерность массива указателей
#define MAX 4

template <typename T> class List
{
protected:

    static struct Item
    {
        T* Data[MAX]; //Массив указателей на квлючаемые обьъекты

        //Количество элементов в массиве
        int DataCount;

        Item* Next;

        Item* Prev;

        Item()
        {
            for (int i = 0; i < MAX; i++)
            {
                this->Data[i] = 0;
            }

            this->DataCount = 0;
            this->Next = 0;
            this->Prev = 0;
        }
    };

    //Количество элементов в списке
    int Count;

    Item* First;

    Item* Last;

public:

    List()
    {
        this->First = new Item();
        this->Last = new Item();
        this->Count = 0;
    }

    ~List()
    {
        Item* rootItem = this->First;

        while (Count != 0)
        {
            Item* item = rootItem;
            rootItem = rootItem->Next;
            delete item;
            Count--;
        }
    }

    //Добавить новый пустой элемент списка
    void Add()
    {
        Item* item = new Item();
        
        if (this->Count == 0)
        {
            item->Next = item;
            item->Prev = item;
            this->First = item;
            this->Last = item;
            this->Count++;
            return;
        }

        item->Prev = this->Last;
        item->Next = this->First;
        this->First->Prev = item;
        this->Last->Next = item;
        this->Last = item;

        this->Count++;
    }

     void InsertObject(T* nwValue/*, int index*/)
    {
        if (this->Count == 0) this->Add();
        
        Item* rootItem = this->Last;

        T temp;

        for (int i = 0; i < MAX; i++)
        {
            if ((rootItem->Data[i] == 0)||(*nwValue < *(rootItem->Data[i])))
            {
                T* tempData[MAX];

                for (int j = 0, k = i; k < MAX; k++, j++)
                {
                    tempData[j] = rootItem->Data[k];
                }

                rootItem->Data[i] = nwValue;

                i++;

                for (int j = 0; i < MAX; i++, j++)
                {
                    rootItem->Data[i] = tempData[j];
                }

                rootItem->DataCount++;
                break;
            }
        }
    }

    // Возвращаем количество элементов в списке
    void ReturnCount()
    {
        return this->Count;
    }

    //Выводим на экран внутреннюю структуру
    void ReturnDatabyIndex()
    {
        Item* item = this->First;
        for (int i = 0; i < this->Count; i++)
        {
            printf("ListItem #%d:\n", i);
            for (int j = 0; j < MAX; j++)
            {
                printf("\tobject #%d: %d\n", j, (item->Data[j] == 0 ? 0 : *(item->Data[j]))); // Избегаем чтения с 0-ого адреса
            }
            item = item->Next;
        }
    }
};


Если писать переопределение операции сравнения так:

Код

template <typename T> class List
{
...
public:
bool operator< (T nwValue)
    {
        printf("123"); //тут чушь, просто, чтобы было
        return true;
    }
};


То получится совсем не то, что надо.

Я так понял, что

Код

template <typename T> class List
{
...
public:
bool T::operator< (T nwValue)
    {
        printf("123"); //тут чушь, просто, чтобы было
        return true;
    }
};


будет самым близким вариантом, но, почему-то smile, не компилится.

Так что, люди добрые, подскажите как сделать переопределение операций для включаемых объектов так, чтобы они (операции) работали. Ну, или хотя бы направление, куда копать.

Это сообщение отредактировал(а) astakor - 19.6.2012, 13:42
PM MAIL   Вверх
math64
Дата 19.6.2012, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



operator< определяется вне шаблона.
Код

List<int> intlist; // operator < для int определён языком программирования, поменять нельзя

class T1 {
public:
bool operator < (const T1& t) const { return x < t.x } // operator < переопределён как метод класса
private:
int x;
};

List<T1> t1list;

class T2 {
public:
friend bool operator <(const T2& t1, const T2& t2); // operator < переопределён как друг класса
private:
int x;
};
bool operator <(const T2& t1, const T2& t2) { return t1.x < t2.x; }

List<T2> t1list;

class T3 {
public:
bool less(const T3& t) const {return x < t.x; } // определён обычный метод для сравнения
private:
int x;
};
bool operator <(const T3& t1, const T3& t2) { return  t1.less(t2); }

List<T3> t1list;

PM   Вверх
baldina
Дата 19.6.2012, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(astakor @  19.6.2012,  07:41 Найти цитируемый пост)
Также надо переопределить операции сравнения включаемых объектов.

переопределение операции сравнения - дело сравниваемого типа, а не контейнера. для некоторых типов этого вообще нельзя сделать, например для встроенных.
Цитата(astakor @  19.6.2012,  07:41 Найти цитируемый пост)
почему-то , не компилится.

что именно не компилится?
Цитата(astakor @  19.6.2012,  07:41 Найти цитируемый пост)
bool T::operator< (T nwValue)

это только если operator< член класса T, но об этом типе в шаблоне мы мало что знаем и уж никак не можем его модифицировать (правда, можем наследовать).
поможет функция не-член класса, с двумя аргументами
Код

bool operator< (const T& lhs,   const T& rhs) {
  // returns  lhs < rhs
  printf("123"); //тут чушь, просто, чтобы было
  return true;  
}

однако я совершенно не понимаю как это может пригодиться, ведь о T (в Вашей постановке) мы ничего не знаем, значит не знаем как сравнивать
PM MAIL   Вверх
borisbn
Дата 19.6.2012, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(baldina @  19.6.2012,  09:47 Найти цитируемый пост)
// returns  lhs < rhs

низя. будет зацикливание


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 19.6.2012, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



это лишь спецификация
PM MAIL   Вверх
astakor
Дата 19.6.2012, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 19.6.2012

Репутация: нет
Всего: нет



Цитата(math64 @  19.6.2012,  09:43 Найти цитируемый пост)
operator< определяется вне шаблона.


Спасибо, попробую у себя.


Цитата(baldina @  19.6.2012,  09:47 Найти цитируемый пост)
для некоторых типов этого вообще нельзя сделать, например для встроенных.


Код

#include "list.h"
#include <stdio.h>

void main()
{
    List<int> myList;
    ...
    myList.ReturnDatabyIndex();
}


Т.е., по заданию, тип данных включаемых объектов int или char.

Цитата(baldina @  19.6.2012,  09:47 Найти цитируемый пост)
что именно не компилится?


Код

template <typename T> class List{
...
public:
bool T::operator< (T nwValue)    { 
       printf("123"); //тут чушь, просто, чтобы было
        return true;    
}
};


Error    1    error C3254: 'List<T>' : class contains explicit override 'T::<' but does not derive from an interface that contains the function declaration    list.h
Error    2    error C2838: '<' : illegal qualified name in member declaration    list.h
Error    3    error C2825: 'T': must be a class or namespace when followed by '::'    list.h
Error    4    error C2039: '<' : is not a member of '`global namespace''    list.h
Error    5    error C2146: syntax error : missing ';' before identifier '<' list.h
Error    6    error C2327: 'List<T>::T' : is not a type name, static, or enumerator    list.h
Error    7    error C4430: missing type specifier - int assumed. Note: C++ does not support default-int    list.h

Это сообщение отредактировал(а) astakor - 19.6.2012, 12:29
PM MAIL   Вверх
xvr
Дата 19.6.2012, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(astakor @  19.6.2012,  07:41 Найти цитируемый пост)
Также надо переопределить операции сравнения включаемых объектов.

Если это трактовать как написанно, то это не задача самого List'а, а задача того T, которое в него подается
Видимо хотели получить возможность задавать функтор для сравнения T в шаблоне List'а
Посмотрите, как это сделано в stl для std::list<> -
Код

template<class T, class Compare = std::less<T> >
class List {
...
};


PM MAIL   Вверх
astakor
Дата 19.6.2012, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 19.6.2012

Репутация: нет
Всего: нет



Цитата(xvr @  19.6.2012,  12:43 Найти цитируемый пост)
Видимо хотели получить возможность задавать функтор для сравнения T в шаблоне List'а


Вообще, нужно, чтобы в методе List'a
например:
Код

void InsertObject(T* nwValue/*, int index*/)
    {
        if (this->Count == 0) this->Add();
        
        Item* rootItem = this->Last;

        T temp;

        for (int i = 0; i < MAX; i++)
        {
            if ((rootItem->Data[i] == 0)||(*nwValue < *(rootItem->Data[i]))) // вот тут оператор сравнения
            {
                ...
            }
        }
    }


использовался переопределенный оператор сравнения
Код

(*nwValue < *(rootItem->Data[i]))


Т.е., насколько я понял, это

Код

bool operator< (T& right)



Цитата(xvr @  19.6.2012,  12:43 Найти цитируемый пост)
Посмотрите, как это сделано в stl для std::list<> 


Посмотреть-то посмотрел, но догадаться как это использовать для нужного результата не получается :( 
Буду рад подсказке smile
PM MAIL   Вверх
xvr
Дата 19.6.2012, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(astakor @  19.6.2012,  13:52 Найти цитируемый пост)
Буду рад подсказке

Вместо явного *nwValue < *(rootItem->Data[i]) вызывается compare_object(*nwValue,*(rootItem->Data[i])) Где compare_object есть -
Код

template<class T, class Compare = std::less<T> >
class List {
 Compare compare_object;
...
};
Стандартный std::less<T> устроен так:
Код

template<class T>
class less {
public:
 static operator () (const T& op1, const T& op2) {return op1<op2;}
}:
Т.е. получается как у вас. Отличие от того, как у вас в том, что при создании List можно подать свой функциональный класс Compare, переопределив таким образом операцию сравнения для T для конкретного экземпляра List'а

Ну например, у вас T есть такая структура -
Код

struct MyT {
 int f1;
 int f2;
};
И вы хотите сделать 2 разных List'а от MyT со сравнением по первому полю (MyT::f1) и по второму (MyT::f2). C bool operator<(const MyT&, const MyT&); вы этого сделать не сможете, т.к. оператор < только один, а вам надо 2 разных  smile 


Это сообщение отредактировал(а) xvr - 19.6.2012, 14:07
PM MAIL   Вверх
astakor
Дата 19.6.2012, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 19.6.2012

Репутация: нет
Всего: нет



xvr, большое Вам спасибо, теперь все стало понятно smile

Думаю, вопрос решен, благодарю всех за участие smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0584 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.