Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > библиотека шаблонов


Автор: Andrej23 28.10.2010, 16:31
Доброго времени суток.

Собственно такая вот загвоздка вышла:

Пытаюсь сделать шаблон.
Шаблон сам нормально компилируется, но при его вызове vs2005 выдает ошибку: 

error C2597: illegal reference to non-static member 'Indicators::Regr'

Шаблон объявил так:
Код

template <typename T,typename Tb,typename Tv,typename Tvb,Tv T::*field,Tvb Tb::*fieldB> double StdDevRegTempl(long index, long Len, T const *array1, Tb const *arrayB);


Вызываю его так:

Код

//здесь выводится рассчитанное обычной ф-ией значение и хочу вывести следом значение, посчитанное шаблоном. 

printf ("StdDevReg:   %f template:  %f\n",Instr.i[500].sko_reg[0], StdDevRegTempl <class Tick, class Indicators, double, double, &Tick::Price, &Indicators::Regr[0]>(500,period,Instr.z, Instr.i));


компилятор на вызов шаблона ругается т.к.  Indicators::Regr - это массив из 20 элементов double, хотя и даю адрес конкретной ячейки массива (типа double).

собственно при вызове используются массивы с элементами типа класс. Сама структура:

Код

class Tick  
{
public:
    double  Price, Open,High,Low,Close;
};

class Indicators
{
public:
    double    Regr[20],    sko_reg[20];
};

class StockNumber
{
public:
    Tick z[NumQuotes];    //ряд тиковых данных, сейчас использую как минутки
    Indicators i[NumQuotes]; //класс с индикаторами
};

StockNumber Instr;


Как правильно изменить объявление ф-ии чтобы можно было задавать параметром элемент массива (чтобы можно было сказать &Indicators::Regr[0]  )?

Автор: Andrej23 28.10.2010, 17:10
В принципе вызвал шаблон, считающий  значение  Indicators::Regr[0] прямо из шаблона StdDevRegTempl , но остался общий вопрос - как можно сделать вызов значения напрямую, без промежуточного расчета чтобы сделать шаблон StdDevRegTempl еще более общим.

Попробовал сделать кол-во элементов массива константой, не помогло:

Код

const int NumCellsInd = 20;

class Indicators
{
public:
    double    Regr[NumCellsInd],    sko_reg[NumCellsInd];
};


Всё равно пишет, что 

illegal reference to non-static member 'Indicators::Regr'

Автор: rudvil 28.10.2010, 20:44
Компилятор же пишет, что "так" использовать не-статические члены класса нельзя, соответственно нужно объявить их статическими.
Код
static double    Regr[NumCellsInd],    sko_reg[NumCellsInd];

Автор: Andrej23 29.10.2010, 15:21
У меня массив Instr.i[] с объектами этого класса. Если сделать члены класса статическими, то получится по одному экземпляру массива-члена класса на весь массив объектов этого класса.

Похоже пока что просто оставлю расчет с вызовом шаблона изнутри другого  шаблона. Работает медленнее, но работает.

А как перейду на с++, тогда по-другому попробую (несколько веток назад подсказали 2 варианта, возможно во втором варианте такой фокус пройдет).

Автор: Master01 29.10.2010, 19:15
Код

printf ("StdDevReg:   %f template:  %f\n",Instr.i[500].sko_reg[0], StdDevRegTempl <class Tick, class Indicators, double, double, &Tick::Price, &Indicators::Regr[0]>(500,period,Instr.z, Instr.i));


Очень маловероятно, что такой код вообще будет работать, поскольку все параметры шаблона должны быть известны в момент компиляции! А тут у вас передаётся адрес поля &Tick::Price и &Indicators::Regr[0] которые на этапе компиляции никак известны быть не могут.

Автор: Andrej23 1.11.2010, 14:39
Цитата(Master01 @  29.10.2010,  19:15 Найти цитируемый пост)
у вас передаётся адрес поля &Tick::Price и &Indicators::Regr[0] которые на этапе компиляции никак известны быть не могут. 


Проблемы возникают только с адресом ячейки массива-члена класса. С членом класса Price никаких проблем не было.

Вот в этой ветке мне дали 2 примера, первый у меня отлично работает:

http://forum.vingrad.ru/forum/topic-313153/kw-%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD-%D1%87%D0%BB%D0%B5%D0%BD-%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0.html

Автор: Master01 1.11.2010, 22:54
угу, признаю был не прав. Я просто вообще не в курсе был про ссылки на члены-данные класса ....

Я тут почитал Страуструпа smile И насколько я понимаю

Код

struct {
 int a[3]
 };

равносильно
Код

struct {
 int a[2];
 int addr; // -- вот это и будет именно то смещение которое вы искали для a[3]. (хотя не уверен если это гарантируется стандартом)
}

Так что можно, например, написать какой-то темплейт который будет автоматом разворачиваться в нечто подобное, а потом брать ссылку на этот самый addr и кастить через reinterpret_cast .... да простят меня великии за такое smile

Но это ужасно! и так делать не надо smile

Вообщем, я бы предложил вам лучше передавать ссылки не на сами членны-данные класса, а на некоторый метод класса, который их возвращает? Гибкость таже (и даже больше, так как метод может предварительно эти данные обработать ещё), но с другой стороны, придётся писать такие методы конечно...

Вот код, для примера (немного переработанный оригинальный код djamshud-а, взятый по той линке, что вы мне дали)
Код

#include<stdio.h>

struct Test
{
    double a;
    double b[3];
    double c;

    double get() const { return b[2]; }
};



template<typename T, typename Tv, Tv (T::*func)() const >
Tv sum(T const *arr, size_t len)
{
    Tv res = 0;

    for(size_t i = 0; i < len; i++)
        res += (arr[i].*func)();

    return res;
}

int main()
{
    Test arr_test[]={ {1, {10,20,30}, 5}, {4, {0.1, 0.2, 0.3}, 7} };  

    double res = sum<Test, double, &Test::get>
        (arr_test, sizeof(arr_test)/sizeof(*arr_test));
    
    printf("%f\n",res);

    return 0;
}



Спасибо за инфу про ссылки на члены-данные класса smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)