Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Ced от Май 06, 2017, 11:54



Название: Про templat
Отправлено: Ced от Май 06, 2017, 11:54
Коллеги, подскажите можно ли иметь шаблонный метод в классе, который не является template?


Название: Re: Про templat
Отправлено: ViTech от Май 06, 2017, 12:52
Можно.


Название: Re: Про templat
Отправлено: Igors от Май 06, 2017, 13:06
[off]Ну вот, началось пагубное увлечение. "Коготок увяз - всей птичке пропасть"  :'([/off]


Название: Re: Про templat
Отправлено: Ced от Май 06, 2017, 19:35
[off]Ну вот, началось пагубное увлечение. "Коготок увяз - всей птичке пропасть"  :'([/off]

Я заметил. Но задача реально того требует.


Название: Re: Про templat
Отправлено: Ced от Май 06, 2017, 22:16
Можно.

Спасибо. Еще вопрос. Имеется вот такая конструкция
Код:
template <typename T>class X : public Y
При создании объекта класса X сперва запускается конструктор Y. Y не template.
Могу ли я определить значение Т в ходе выполнения конструктора Y?
Или может можно сделать иначе, так, чтобы сперва создать объект Y, а после выбрать значение Т?


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 11:28
Что то я не пойму
Код:
template <typename T>class Parametr : public ParametrName
{
.......
    Parametr<T> ();
...........
};

Parametr<float> *x;

x = new Parametr<float>;

И в итоге:
Код:
ошибка: undefined reference to `Parametr<float>::Parametr()'

Что не так?


Название: Re: Про templat
Отправлено: Igors от Май 07, 2017, 13:00
Могу ли я определить значение Т в ходе выполнения конструктора Y?
Или может можно сделать иначе, так, чтобы сперва создать объект Y, а после выбрать значение Т?
Нет. Темплаты - они как бы "статики", т.е. все известно и решается на этапе компиляции, никаких "динамических" манипуляций с типом нет.

Что то я не пойму
Код
C++ (Qt)
template <typename T>class Parametr : public ParametrName
{
.......
//    Parametr<T> ();
     Parametr();
...........
};
 
template<typename T>
Parametr<T>::Parametr( void )
{
..
}
 



Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 13:08

Код
C++ (Qt)
template <typename T>class Parametr : public ParametrName
{
.......
//    Parametr<T> ();
     Parametr();
...........
};
 
template<typename T>
Parametr<T>::Parametr( void )
{
..
}
 

Попробовал. Результат тот же. Компилятор не желает видеть, что у класса Parametr есть такой конструктор.
Но вообще это тестовый пример. Я все упростил от безысходности. Бьюсь, как в стенку. А задумка в целом такова:
Есть шаблонный класс. Хочу создать вектор ссылок на объекты этого класса. За тем определить длину вектора. Для каждого элемента вектора динамически создать объект. У каждого объекта свое значение параметра Т. Это возможно?


Название: Re: Про templat
Отправлено: Igors от Май 07, 2017, 13:40
Попробовал. Результат тот же. Компилятор не желает видеть, что у класса Parametr есть такой конструктор.
Учтите что тело конструктора должно находиться в той же "единице трансляции"
Но вообще это тестовый пример.
Тем лучше, выкладывайте его как zip с компилируемым примером внутри
А задумка в целом такова:
Есть шаблонный класс. Хочу создать вектор ссылок на объекты этого класса. За тем определить длину вектора. Для каждого элемента вектора динамически создать объект. У каждого объекта свое значение параметра Т. Это возможно?
Да, это довольно популярная задача, только "вектор ссылок" вряд ли, наверное имелся ввиду "вектор указателей". Пишете базовый класс, от него наследуете темплейт класс (как Вы и начали делать) и работаете через виртуалы базового класса.


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 13:49
Цитировать
Учтите что тело конструктора должно находиться в той же "единице трансляции"

Расположение таково:
Класс Parametr находится в файле Parametrs.h
Конструктор - в файле Parametrs.cpp
Объект *x пытаюсь создавать в файле MyServer.cpp как локальную переменную в конструкторе класса MyServer.
Все в одном проекте.
Компилятор не ругается на объявление Parametr<float> *x и стало быть класс Parametr он видит. А вот наличие в нем конструктора не желает признавать.
Я сперва пользовался другим конструктором с параметрами. Потом решил исключить все возможные причины ошибки и создал кнструктор предельно простой.
Это не помогло.

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


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 14:15
Цитировать
Учтите что тело конструктора должно находиться в той же "единице трансляции"
До меня дошло наконец. Спасибо. Это для шаблонов такая особенность?
И как же быть? Описывать конструктор непосредственно в теле класса? Или как это принято решать?
Про это где-то написано?


Название: Re: Про templat
Отправлено: Igors от Май 07, 2017, 14:28
Дошло наконец. Спасибо. Это для шаблонов такая особенность?
Да, в момент "инстанциации" все тела должны быть видимы
И как же быть? Описывать конструктор непосредственно в теле класса?
Можно и так, это несколько "замусоривает" хедер, но - дело вкуса. Я обычно сваливаю тела в файл
напр "MyClass_Templates.cpp", который включаю НЕ в проект, а в хедер
Код
C++ (Qt)
// файл MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
 
template<class T>
class MyClass {
...
};
#include "MyClass_Templates.cpp"
 
#endif  // MYCLASS_H
 

[off]
Но задача реально того требует.
Увлечение этой заразой сгубило немало хороших ребят [/off]


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 14:35
Спасибо огромное. Бился с этим три дня непрерывно. Нигде не смог прочитать. С этим понятно. Помогите пожалуйста еще с вектором.

Я предполагаю объявить его так

Код:
template <typename T> class X
{

......

};

......

int n = 10;


QVector<X<typename T>> *Y = new QVector(n)

.......

Y<float>[j] = new X<float>(.....);


Это корректно?


Название: Re: Про templat
Отправлено: Igors от Май 07, 2017, 15:47
Я предполагаю объявить его так

Код:
template <typename T> class X
{

......

};

......

int n = 10;


QVector<X<typename T>> *Y = new QVector(n)

.......

Y<float>[j] = new X<float>(.....);


Это корректно?
Нет.
Код
C++ (Qt)
QVector<X<typename T>> *Y = new QVector(n)
 
Это уже не объявление а инстациирование, здесь может быть только конкретный тип, напр float. но никак не typename. Правильно напр так
Код
C++ (Qt)
template <typename T>
class X : public BaseElement
{
};
 
QVector<BaseElement *> * ptrY = new QVector<BaseElement *> (n);
(*ptrY)[0] = new X<float>(..);
 
В контейнере могут быть только эл-ты одного типа, поэтому придется там хранить указатели на базовый класс, напр BaseElement.

И опять Вы допускаете ту же ошибку - обращение к массиву векторов вместо обращения к эл-ту вектора


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 15:50
Спасибо. Сняли с меня огромную головную боль. Раньше никогда с шаблонами не работал. Очень помогли.


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 19:28
Еще раз прошу подсказки. Как можно внутри конструктора шаблона узнать, какой тип данных подан на вход?


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 21:48
Например так
Код
C++ (Qt)
template <typename T>
class MyCoolClass {
public:
   MyCoolClass(const T &value)  
       : value_(value)
   {
   }
private:
   T value_;
};


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 21:52
Igors,
Лучше не указывать void при отсутствии параметров в объявлении метода, функции.
1. Это pure c style
2. Это дезориентирует новичков.
Я знаю людей, которые свято верят, что в относительно старых версиях gcc без void в скобках код не скомпилируется.


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 21:53
Например так
Код
C++ (Qt)
template <typename T>
class MyCoolClass {
public:
   MyCoolClass(const T &value)  
       : value_(value)
   {
   }
private:
   T value_;
};

Честно сказать, я не понял, как это работает. Может поясните?


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:04
Есть шаблонный класс, который хранит в себе value_ типа T.
Тип T задаётся пользователем шаблона например так
Код
C++ (Qt)
double d = 123.0;
MyCoolClass<int> instance(d);
В примере шаблон инстанцируется типом int, конструктор принимает int конвертируя double по всем канонам :)


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:08
Можно конкретнее, что именно за задача стоит. Вдруг шаблоны и не нужны...


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 22:09
Есть шаблонный класс, который хранит в себе value_ типа T.
Тип T задаётся пользователем шаблона например так
Код
C++ (Qt)
double d = 123.0;
MyCoolClass<int> instance(d);
В примере шаблон инстанцируется типом int, конструктор принимает int конвертируя double по всем канонам :)

Или я Вас опять не понял, или плохо объяснил, чего хочу. Проблема вот в чем:
Некоторые операции не могут быть реализованы одинаково для различных типов данных. Это очевидно.
В конструкторе класса я совершаю с данными такие операции. Чтобы корректно обрабатывать различные типы, я хочу знать, каким типом инстанцирован тот конкретный объект, для которого сейчас запущен конструктор. Мне кажется, Ваш код эту проблему не решает. Мне нужно получить информацию об инстанцирующем типе в виде признака. по которому можно организовать ветвление алгоритма.


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 22:12
Можно конкретнее, что именно за задача стоит. Вдруг шаблоны и не нужны...

Обрабатывается поток данных. Данные поступают в виде строк. Каждая строка содержит набор значений. Значения эти могут быть разного типа и наперед их типы не известны. Для описания структуры потока используется специальный файл. Из него можно считать, что придет в потоке. При каждой обработке этот файл может быть различным.


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:24
Задачей не проникся.
Для определения типа:
Можно воспользоваться в крайнем случае
http://www.cplusplus.com/reference/type_traits/

Можно немножко усложнить шаблон путем специализации
Код
C++ (Qt)
template <typename T>
struct MyCoolFunctions;
Код
C++ (Qt)
template<>
struct MyCoolFunctions<float> {
   static doSomething(float value) {
       std::cout << value;
   }
};

Код
C++ (Qt)
template<>
struct MyCoolFunctions<double> {
   static doSomething(double value) {
       std::cerr << value;
   }
};
и т.д. специализируем все необходимые нам обработки

теперь сам шаблон
Код
C++ (Qt)
template<typename T, typename Traits=MyCoolFunctions<T>>
class MyCoolClass {
public:
   MyCoolClass(const T &value) {
       Traits::doSomething(value);
   }
}

инстанцируем так:
Код
C++ (Qt)
double d = 123;
float f = 456;
 
MyCoolClass<double> floatInstance (d); // cerr
MyCoolClass<float> floatInstance (f); // cout
 


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:28
К слову, шаблоны - инструмент времени компиляции.
А чтение потоков и файлов происходит во время выполнения программы.


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:31
Предлагаю подробнее разжевать задачу. Привести 2-3 примера, того что приходит в потоке данных и как при описании структуры используется файл (пример что он содержит).


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 22:34
Для задачи я нашел решение. Оно конечно не универсально, но в моем случае вполне пригодно. Теперь интересуюсь уже из любопытства, есть ли что-то менее костыльное. Предложенные Вами способы честно говоря не очень порадовали. По ссылке описана возможность для многих типов, но я скажем не нашел там варианта узнать про тип bool. Второй способ таков, что можно и не пользоваться шаблонами. Просто ветвим алгоритм для каждого типа и все. Сейчас у меня есть ветвление при инстанцировании. Я считываю файл настроек, узнаю о типе каждого параметра и инстанцирую соответствующий класс в нужной ветке. Дальше все вроде красиво.


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 22:39
Предлагаю подробнее разжевать задачу. Привести 2-3 примера, того что приходит в потоке данных и как при описании структуры используется файл (пример что он содержит).
Вот пример такого файла, если интересно
Код:
[Parametr]
[Name]
t
[Comment]
Время
[Type]
3
[Sorce]
0
[Parametr]
[Name]
MH
[Comment]
Наработка
[Type]
2
[Sorce]
2
[Parametr]
[Name]
R41
[Comment]
Тв на вх. Д (1)
[Dimention]
град. Цел.
[Type]
0
[Sorce]
0
[minPossible]
-50
[minMarginal]
-50
[maxMarginal]
50
[maxPossible]
50

А вот код, который его читает:
Код:
    QTextStream *in1 = new QTextStream(parametrsFile);
    while(!in1->atEnd())
    {
        ParametrName  temp (*in1);
        switch (temp.getType())
        {
    case Parametr<float>::continuous:
        {
            Parametr<float> tmp(*in1, temp);
            mainBuffer.append(new Parametr<float>(tmp));
            break;
        }
    case Parametr<bool>::discreteYesNo:
        {
            Parametr<bool> tmp(temp);
            mainBuffer.append(new Parametr<bool>(tmp));
            break;
        }
    case Parametr<long>::time:
        {
            Parametr<long> tmp(*in1, temp);
            mainBuffer.append(new Parametr<long>(tmp));
            break;
        }
    case Parametr<QDateTime>::dateTime:
        {
            Parametr<QDateTime> tmp(temp);
            mainBuffer.append(new Parametr<QDateTime>(tmp));
            break;
        }
    default:
            break;
        }
    }


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:48
Ну, вроде, это единственный вариант делать именно то, что вы делаете.
Единственное, что могу предложить, это только сделать мапу данных и указателей на функцию типа:
Код
C++ (Qt)
template <typename T>
ParamBase *makeNewParam(const QString &value) {
return new Param<T>(value);
}
 

Код
C++ (Qt)
static const std::map<QString, std::function<ParamBase*(const QString &)> funMap= {
   "bool", makeNewParam<bool>,
   "int", makeNewParam<int>
};

Поведение конструктора Param описать с помощью Traits, как было написано выше.

Вызывать так
Код
C++ (Qt)
const QString type("bool");
const QString myData("data");
myParams += funMap.at(type)(myData);


Название: Re: Про templat
Отправлено: Ced от Май 07, 2017, 22:51
Ну, вроде, это единственный вариант делать именно то, что вы делаете.
Единственное, что могу предложить, это только сделать мапу данных и указателей на функцию типа:
Код
C++ (Qt)
template <typename T>
ParamBase *makeNewParam(const QString &value) {
return new Param<T>(value);
}
 

Код
C++ (Qt)
static const std::map<QString, std::function<ParamBase*(const QString &)> funMap= {
   "bool", makeNewParam<bool>,
   "int", makeNewParam<int>
};

Поведение конструктора Param описать с помощью Traits, как было написано выше.

Вызывать так
Код
C++ (Qt)
const QString type("bool");
const QString myData("data");
funMap.at(type)(myData);

Спасибо. Это намотаю на ус. Думаю, пригодится, когда буду рефакторить эту писанину. Сейчас просто времени очень мало. Приходится лепить с листа. Качество кода меня лично удручает, но такими темпами я лучше не способен. Очень надеюсь, что будет возможность потом все это причесать.


Название: Re: Про templat
Отправлено: __Heaven__ от Май 07, 2017, 22:53
Имхо, xml структура для такого файла здесь уместнее.
Ладно, удачи.


Название: Re: Про templat
Отправлено: Igors от Май 08, 2017, 11:45
Спасибо. Это намотаю на ус. Думаю, пригодится, когда буду рефакторить эту писанину. Сейчас просто времени очень мало. Приходится лепить с листа. Качество кода меня лично удручает, но такими темпами я лучше не способен. Очень надеюсь, что будет возможность потом все это причесать.
Весьма слабые угрызения совести :)

Вот пример такого файла, если интересно
Ага, ну я так и знал, Вы совершенно напрасно связались с темплейтами, здесь прямо-таки напрашивается QVariant. Или др реализация variant, возможно даже на темплейтах но уже делающая много черновой работы которую сейчас Вам нужно реализовывать самому



Название: Re: Про templat
Отправлено: Ced от Май 08, 2017, 11:51
Цитировать
Ага, ну я так и знал, Вы совершенно напрасно связались с темплейтами, здесь прямо-таки напрашивается QVariant. Или др реализация variant, возможно даже на темплейтах но уже делающая много черновой работы которую сейчас Вам нужно реализовывать самому

Не сомневаюсь, что мною выбран не лучший вариант реализации. Причина в следующем: С шаблонами я раньше не работал, но понимаю, что это такое. Про QVariant  я пока не знаю ничего. Времени на изучение сейчас у меня нет. Я рассчитываю сделать вариант "на коленке", а после получить время на рефакторинг. Некоторые ошибки в коде я делаю намеренно, чтобы у заказчика не было возможности сказать "Работает и ладно". Смешно? - Думаю, не всем. В такой ситуации работают многие программисты. Не многие решаются попытаться ее изменить. Я решил попробовать.


Название: Re: Про templat
Отправлено: Igors от Май 08, 2017, 12:40
Не сомневаюсь, что мною выбран не лучший вариант реализации. Причина в следующем: С шаблонами я раньше не работал, но понимаю, что это такое. Про QVariant  я пока не знаю ничего. Времени на изучение сейчас у меня нет.
А вот время на эксперименты с темплейтами нашлось, по Вашим же словам бились 3 дня. Собственно в этом их опасность и есть. Вещь сама по себе неплохая, иногда даже необходимая. Но очень часто она увлекает программиста в мифический мир обобщений. Масса времени уходит на то как же пристроить всякие "хитросплетения". Наконец все получилось, ура! Пройдет эдак полгода, глянешь опять этот код - ничего хорошего, иной раз и сам забыл что хотел.

Я рассчитываю сделать вариант "на коленке", а после получить время на рефакторинг. Некоторые ошибки в коде я делаю намеренно, чтобы у заказчика не было возможности сказать "Работает и ладно". Смешно? - Думаю, не всем. В такой ситуации работают многие программисты. Не многие решаются попытаться ее изменить. Я решил попробовать.
А в чем заключается Ваше (мужественное) решение изменить? Пока ни в чем, просто тешите себя надеждами. Жизнь покажет..


Название: Re: Про templat
Отправлено: Ced от Май 08, 2017, 12:49
Согласен. Жизнь покажет:)


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 01:09
И снова я к Вам с вопросом

Код
C++ (Qt)
template <typename T>
class X : public BaseElement
{
};
 
QVector<BaseElement *> * ptrY = new QVector<BaseElement *> (n);
(*ptrY)[0] = new X<float>(..);
 

Реализовал такую схему. А как теперь через элементы QVector добраться до свойств или методов объектов класса Х? Я из не вижу.


Название: Re: Про templat
Отправлено: Igors от Май 09, 2017, 04:49
Реализовал такую схему. А как теперь через элементы QVector добраться до свойств или методов объектов класса Х?
А какие методы (зависящие от темплейт типа) нужны? Не хочу показаться навязчивым, но если время поджимает то лучше соскочить на QVariant, выглядит примерно так
Код
C++ (Qt)
class Parametr {
...
QString m_name, m_comment;
QVariant m_value;
...
};
 
QList<Parametr> theParamList;
theParamList << Parametr("name", "comment", QVariant((float) value));
...
 
Заметьте как стало "приятнее". Можно спокойно копировать как сам theParamList, так и его элементы. А в варианте с темплейт для этого нужно приложить усилия.

Или хотите все-таки "помучить котов"?  :)


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 12:01
А какие методы (зависящие от темплейт типа) нужны? [/quote]

Код:
class ParametrName
{
private:
        int  type;
        int  sorce;
      float  multiplier;
    QString  name;
    QString  discription;
    QString  dimension;

public:
    ParametrName (QTextStream &input);
    ParametrName (const ParametrName& toCopy);

        int  getType        ();
        int  getSorce       ();
      float  getMultiplier  ();
    QString  getDimension   ();
    QString  getName        ();
    QString  getDiscription ();

    void  setType        (    int  toSet);
    void  setSorce       (    int  toSet);
    void  setMultiplier  (  float  toSet);
    void  setDimension   (QString  toSet);
    void  setName        (QString  toSet);
    void  setDiscription (QString  toSet);
};

template <typename T> class MyQueueBuffer
{
private:
    int  bufferLength;
    QQueue<MyData<T>> myQueueBuffer;
public:
    MyQueueBuffer<T> (const MyQueueBuffer <T>& toCopy);
    MyQueueBuffer<T> (int  length);

       T  dequeue();
    void  enqueue(const T &t);
};

template <typename T> MyQueueBuffer<T>::MyQueueBuffer (const MyQueueBuffer <T>& toCopy)
{
    bufferLength  = toCopy.bufferLength;
    myQueueBuffer = toCopy.myQueueBuffer;
}

template <typename T> MyQueueBuffer<T>::MyQueueBuffer (int  length)
{
    bufferLength = length;
}

template <typename T>class Parametr : public ParametrName
{
public:
    enum
    {
        continuous    = 0,
        discreteYesNo = 1,
        time          = 2,
        dateTime      = 3
    } parametrTypes;

    enum
    {
        measured           = 0,
        calculated         = 1,
        calculatedExternal = 2
    } parametrSource;

private:
                   T  minPossibleValue;
                   T  maxPossibleValue;
                   T  minMarginalValue;
                   T  maxMarginalValue;

    MyQueueBuffer<T> *buffer;
public:
    Parametr<T> (const Parametr <T>& toCopy);
    Parametr<T> (const ParametrName& toCopy);
    Parametr<T> (QTextStream &input, ParametrName const& toCopy);

       T  getMinPossibleValue ();
       T  getMaxPossibleValue ();
       T  getMinMarginalValue ();
       T  getMaxMarginalValue ();

    void  setMinPossibleValue (T  minToSet);
    void  setMaxPossibleValue (T  maxToSet);
    void  setMinMarginalValue (T  minToSet);
    void  setMaxMarginalValue (T  maxToSet);

    void  initBuffer (int  length);
};

Нужен доступ к
Код:
          MyQueueBuffer<T> *buffer,                    T  minPossibleValue;
                   T  maxPossibleValue;
                   T  minMarginalValue;
                   T  maxMarginalValue;


Название: Re: Про templat
Отправлено: Igors от Май 09, 2017, 13:25
Нужен доступ к
Т.е. к тому что разрисовали геттерами/сеттерами. Объявляете чистый виртуал в базовом классе, напр
Код
C++ (Qt)
class ParametrName {
..
virtual double getMinPossibleValue( void ) = 0;
..
};
 
И реализуете его в template наследнике
Код
C++ (Qt)
template <typename T>
class Parametr : public ParametrName {
..
double getMinPossibleValue( void ) override { return minPossibleValue; }
..
};
 
Если понадобится выписываете частичную специализацию


Название: Re: Про templat
Отправлено: Old от Май 09, 2017, 13:35
Объявляете чистый виртуал в базовом классе, напр
А какой смысл в этом виртуале? Для чего его переопределять в потомке (шаблоне!), если все равно типы максимума/минимума всегда ограничены double?


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 13:38
Объявляете чистый виртуал в базовом классе, напр
А какой смысл в этом виртуале? Для чего его переопределять в потомке (шаблоне!), если все равно типы максимума/минимума все равно ограничены double?

А что меняется от типа?


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 13:39
Нужен доступ к
Т.е. к тому что разрисовали геттерами/сеттерами. Объявляете чистый виртуал в базовом классе, напр
Код
C++ (Qt)
class ParametrName {
..
virtual double getMinPossibleValue( void ) = 0;
..
};
 
И реализуете его в template наследнике
Код
C++ (Qt)
template <typename T>
class Parametr : public ParametrName {
..
double getMinPossibleValue( void ) override { return minPossibleValue; }
..
};
 
Если понадобится выписываете частичную специализацию

Значит мне под каждый возможный тип определять отдельную виртуальную функцию?


Название: Re: Про templat
Отправлено: Old от Май 09, 2017, 13:40
А что меняется от типа?
Не знаю, что у вас меняется от типа? Для чего-то вы шаблон завели? :)


Название: Re: Про templat
Отправлено: Old от Май 09, 2017, 13:42
Значит мне под каждый возможный тип определять отдельную виртуальную функцию?
Это если вы ходите сделать максимально плохо. 


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 13:44
А что меняется от типа?
Не знаю, что у вас меняется от типа? Для чего-то вы шаблон завели? :)

Я вот в каком смысле: Что значит "...ограничены double"? Имеется ввиду, он самый длинный из используемых? или что-то иное?


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 13:48
Значит мне под каждый возможный тип определять отдельную виртуальную функцию?
Это если вы ходите сделать максимально плохо. 

А если не максимально?


Название: Re: Про templat
Отправлено: Old от Май 09, 2017, 13:58
А если не максимально?
Например так. Есть базовый класс ParametrBase, от него наследуются остальные четыре:
ParametrContinuous
ParametrDiscreteYesNo
ParametrTime
ParametrDateTime

У каждого класса будут свои специфичные данные и методы. У ParametrContinuous будут описаны минимумы и максимумы, которые не нужны для других типов, у  ParametrTime будут методы для хранения времени и т.д.

А в базовый класс стоит выносить только общие методы, например метод toString, который переопределяется в наследниках и правильно формирует значение параметра в строку для дальнейшего отображения.
 


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 14:01
А если не максимально?
Например так. Есть базовый класс ParametrBase, от него наследуются остальные четыре:
ParametrContinuous
ParametrDiscreteYesNo
ParametrTime
ParametrDateTime

У каждого класса будут свои специфичные данные и методы. У ParametrContinuous будут описаны минимумы и максимумы, которые не нужны для других типов, у  ParametrTime будут методы для хранения времени и т.д.

А в базовый класс стоит выносить только общие методы, например метод toString, который переопределяется в наследниках и правильно формирует значение параметра в строку для дальнейшего отображения.
 

Тогда чего шаблон? Я бы под каждый тип данных определить класс и не ломать голову.


Название: Re: Про templat
Отправлено: Old от Май 09, 2017, 14:06
Тогда чего шаблон? Я бы под каждый тип данных определить класс и не ломать голову.
Вот тип параметра ParametrContinuous имело бы смысл сделать шаблоном, если в программе возможны разные типы параметров (целые/реальные).


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 14:17
В итоге решил так:
Код:
template <typename T> class MyQueueBuffer
{
private:
    int  bufferLength;
    QQueue<MyData<T>> myQueueBuffer;
public:
    MyQueueBuffer<T> (const MyQueueBuffer <T>& toCopy);
    MyQueueBuffer<T> (int  length);

       T  dequeue();
    void  enqueue(const T &t);
};

template <typename T> MyQueueBuffer<T>::MyQueueBuffer (const MyQueueBuffer <T>& toCopy)
{
    bufferLength  = toCopy.bufferLength;
    myQueueBuffer = toCopy.myQueueBuffer;
}

template <typename T> MyQueueBuffer<T>::MyQueueBuffer (int  length)
{
    bufferLength = length;
}

class ParametrName
{
private:
        int  type;
        int  sorce;
      float  multiplier;
    QString  name;
    QString  discription;
    QString  dimension;

public:
    ParametrName (QTextStream &input);
    ParametrName (const ParametrName& toCopy);

//    virtual ~ParametrName();

        int  getType        ();
        int  getSorce       ();
      float  getMultiplier  ();
    QString  getDimension   ();
    QString  getName        ();
    QString  getDiscription ();

    void  setType        (    int  toSet);
    void  setSorce       (    int  toSet);
    void  setMultiplier  (  float  toSet);
    void  setDimension   (QString  toSet);
    void  setName        (QString  toSet);
    void  setDiscription (QString  toSet);

    virtual void  initBuffer (int  length);
};

template <typename T>class Parametr : public ParametrName
{
public:
    enum
    {
        continuous    = 0,
        discreteYesNo = 1,
        time          = 2,
        dateTime      = 3
    } parametrTypes;

    enum
    {
        measured           = 0,
        calculated         = 1,
        calculatedExternal = 2
    } parametrSource;

private:
                   T  minPossibleValue;
                   T  maxPossibleValue;
                   T  minMarginalValue;
                   T  maxMarginalValue;

    MyQueueBuffer<T> *buffer;
public:
    Parametr<T> (const Parametr <T>& toCopy);
    Parametr<T> (const ParametrName& toCopy);
    Parametr<T> (QTextStream &input, ParametrName const& toCopy);

       T  getMinPossibleValue ();
       T  getMaxPossibleValue ();
       T  getMinMarginalValue ();
       T  getMaxMarginalValue ();

    void  setMinPossibleValue (T  minToSet);
    void  setMaxPossibleValue (T  maxToSet);
    void  setMinMarginalValue (T  minToSet);
    void  setMaxMarginalValue (T  maxToSet);

    static MyQueueBuffer<T *> mainBufferData (int  number);

    void  initBuffer (int  length);
};

Проверил. Работает.


Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 14:21
И еще. Работа - работой, но всех с праздником Победы!


Название: Re: Про templat
Отправлено: Igors от Май 09, 2017, 14:45
Код:
        int  getType        ();
К слову: здесь (и в др геттерах) не хватает модификатора const

В итоге решил так:
Не понял что решилось :)

Значит мне под каждый возможный тип определять отдельную виртуальную функцию?
Нет, так их просто нельзя будет затем использовать, т.к. виртуалы могут иметь только конкретные типы аргументов и возвращаемых значений. Виртуалы нужны чтобы рулить этой "оравой" разно-типных наследников. Напр пробегаться по контейнеру указателей на базовый тип и однообразно вызывать getMinPossibleValue, не влезая в утомительные разборки какой там тип конкретно.

И еще. Работа - работой, но всех с праздником Победы!
Да, спасибо, и Вас тоже. Хороший праздник!





Название: Re: Про templat
Отправлено: Ced от Май 09, 2017, 14:50
Цитировать
Не понял что решилось :)


Да так и решилось. Наделал виртуалов и сделал функции, возвращающие сылки на массивы. содержащие шаблоны. А работать с этими ссылками буду в обработчиках. которые знают тип данных, с которым работают.


Название: Re: Про templat
Отправлено: Ced от Май 10, 2017, 21:33

[/quote]Ага, ну я так и знал, Вы совершенно напрасно связались с темплейтами, здесь прямо-таки напрашивается QVariant. Или др реализация variant, возможно даже на темплейтах но уже делающая много черновой работы которую сейчас Вам нужно реализовывать самому
[/quote]
Все, сдаюсь. Переделываю на QVariant. C этими шаблонами легче застрелиться.


Название: Re: Про templat
Отправлено: ViTech от Май 11, 2017, 12:46
Все, сдаюсь. Переделываю на QVariant. C этими шаблонами легче застрелиться.

Стреляться из-за шаблонов не стоит. Надо лучше изучить их, хотя бы основы, и применять по назначению :).


Название: Re: Про templat
Отправлено: Ced от Май 12, 2017, 15:21
Стреляться из-за шаблонов не стоит. Надо лучше изучить их, хотя бы основы, и применять по назначению :).

Вероятно с назначением я в этот раз промахнулся. Ну за то изучил основы:)